diff --git a/CHANGELOG.md b/CHANGELOG.md index 67c355bcc7bd8b2d1b450ebc8240d3e19e9b4cf6..ddcbc8c2cc06bbddf7a7a8c694645f0ea1e309b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +0.74.0-beta7 +============= +* Framework improvements + * Exceptions are caught and logged before reaching the Phrase::__toString() method + * Refactored controller actions in the Checkout area + * Refactored controller actions in the Tax area + * Implemented new look & feel for the Edit Order page (View/Edit Order) + * Replaced the end-to-end test for Onepage Checkout with online shipment methods with the scenario test +* Fixed bugs + * Fixed an issue where a success message was absent when adding a product with options from Wishlist to Shopping Cart + * Fixed an issue where an exception was thrown when trying to sort Customer Groups by Tax Class + * Fixed an issue where the background color changed to the “on focus†state when clicking the Admin Menu logo + * Fixed an issue with Mini Shopping Cart containing extra empty space +* GitHub issues + * [#1173] (https://github.com/magento/magento2/pull/1173) -- Change to HttpClient4 from Java client; fix regex issues + * [#1185] (https://github.com/magento/magento2/pull/1185) -- Error message for duplicated phrases not allowed in Generator.php + * [#1199] (https://github.com/magento/magento2/pull/1199) -- Add Event for sales_order_state_change_before during Order->saveState() + * [#1201] (https://github.com/magento/magento2/pull/1101) -- Add customer_validate event + * [#1202] (https://github.com/magento/magento2/pull/1102) -- Email sending events + 0.74.0-beta6 ============= * Framework improvements diff --git a/app/code/Magento/AdminNotification/composer.json b/app/code/Magento/AdminNotification/composer.json index 354ef5fe45ea35de94ce81c1970bbb98e1a889ab..f458a240d3166d604a83b026cf38c06e32ed6247 100644 --- a/app/code/Magento/AdminNotification/composer.json +++ b/app/code/Magento/AdminNotification/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/AdminNotification/view/adminhtml/templates/toolbar_entry.phtml b/app/code/Magento/AdminNotification/view/adminhtml/templates/toolbar_entry.phtml index 4eb8992290adff8b14a85fc98e0f1b7b944a812c..e020a661d4d917d2e61ef793ab0c76bdb2eda699 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/templates/toolbar_entry.phtml +++ b/app/code/Magento/AdminNotification/view/adminhtml/templates/toolbar_entry.phtml @@ -14,12 +14,12 @@ ?> <div data-mage-init='{"toolbarEntry": {}}' - class="notifications-wrapper" + class="notifications-wrapper admin__action-dropdown-wrap" data-notification-count="<?php echo $notificationCount; ?>"> <?php if ($notificationCount > 0) : ?> <a href="<?php echo $block->getUrl('adminhtml/notification/index'); ?>" - class="notifications-action" + class="notifications-action admin__action-dropdown" data-mage-init='{"dropdown":{}}' title="<?php echo __('Notifications'); ?>" data-toggle="dropdown"> @@ -28,7 +28,7 @@ </span> </a> <ul - class="notifications-list" + class="admin__action-dropdown-menu" data-mark-as-read-url="<?php echo $block->getUrl('adminhtml/notification/ajaxMarkAsRead'); ?>"> <?php foreach ($block->getLatestUnreadNotifications() as $notification) : ?> <?php /** @var $notification \Magento\AdminNotification\Model\Inbox*/ ?> @@ -76,7 +76,7 @@ </ul> <?php else : ?> <a - class="notifications-action" + class="notifications-action admin__action-dropdown" href="<?php echo $block->getUrl('adminhtml/notification/index'); ?>" title="<?php echo __('Notifications'); ?>"> </a> diff --git a/app/code/Magento/AdminNotification/view/adminhtml/web/toolbar_entry.js b/app/code/Magento/AdminNotification/view/adminhtml/web/toolbar_entry.js index 43e4869cdf52625f864894e028715f0bc6de40d7..7eb99c590fb4a66a814a18698258bb1b3993e784 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/web/toolbar_entry.js +++ b/app/code/Magento/AdminNotification/view/adminhtml/web/toolbar_entry.js @@ -11,7 +11,7 @@ define([ // Mark notification as read via AJAX call var markNotificationAsRead = function (notificationId) { - var requestUrl = $('.notifications-wrapper .notifications-list').attr('data-mark-as-read-url'); + var requestUrl = $('.notifications-wrapper .admin__action-dropdown-menu').attr('data-mark-as-read-url'); $.ajax({ url: requestUrl, type: 'POST', @@ -33,7 +33,7 @@ define([ if (notificationCount == 0) { // Change appearance of the bubble and its behavior when the last notification is removed - $('.notifications-wrapper .notifications-list').remove(); + $('.notifications-wrapper .admin__action-dropdown-menu').remove(); var notificationIcon = $('.notifications-wrapper .notifications-icon'); notificationIcon.removeAttr('data-toggle'); notificationIcon.off('click.dropdown'); @@ -45,7 +45,7 @@ define([ } $('.notifications-entry-last .notifications-counter').text(notificationCount); // Modify caption of the 'See All' link - var actionElement = $('.notifications-wrapper .notifications-list .last .action-more'); + var actionElement = $('.notifications-wrapper .admin__action-dropdown-menu .last .action-more'); actionElement.text(actionElement.text().replace(/\d+/, notificationCount)); } }, @@ -65,7 +65,7 @@ define([ }; // Show notification description when corresponding item is clicked - $('.notifications-wrapper .notifications-list .notifications-entry').on('click.showNotification', function (event) { + $('.notifications-wrapper .admin__action-dropdown-menu .notifications-entry').on('click.showNotification', function (event) { // hide notification dropdown $('.notifications-wrapper .notifications-icon').trigger('click.dropdown'); diff --git a/app/code/Magento/Authorization/composer.json b/app/code/Magento/Authorization/composer.json index 22341f8d0b4d16e93ce92006994cd36e1fbedb58..7e752b8409c4e92ccb1114620a761fdb81d5f50e 100644 --- a/app/code/Magento/Authorization/composer.json +++ b/app/code/Magento/Authorization/composer.json @@ -3,12 +3,12 @@ "description": "Authorization module provides access to Magento ACL functionality.", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Backend/App/Action/Context.php b/app/code/Magento/Backend/App/Action/Context.php index e6618170e4d6b72683ed960679575649e307dec4..b16e9b05d18047a5420f007e4136cce3177907a5 100644 --- a/app/code/Magento/Backend/App/Action/Context.php +++ b/app/code/Magento/Backend/App/Action/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Backend\App\Action; +use Magento\Framework\Controller\ResultFactory; + /** * Backend Controller context * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -62,6 +64,7 @@ class Context extends \Magento\Framework\App\Action\Context * @param \Magento\Framework\App\ViewInterface $view * @param \Magento\Framework\Message\ManagerInterface $messageManager * @param \Magento\Backend\Model\View\Result\RedirectFactory $resultRedirectFactory + * @param \Magento\Framework\Controller\ResultFactory $resultFactory * @param \Magento\Backend\Model\Session $session * @param \Magento\Framework\AuthorizationInterface $authorization * @param \Magento\Backend\Model\Auth $auth @@ -83,6 +86,7 @@ class Context extends \Magento\Framework\App\Action\Context \Magento\Framework\App\ViewInterface $view, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Backend\Model\View\Result\RedirectFactory $resultRedirectFactory, + ResultFactory $resultFactory, \Magento\Backend\Model\Session $session, \Magento\Framework\AuthorizationInterface $authorization, \Magento\Backend\Model\Auth $auth, @@ -102,7 +106,8 @@ class Context extends \Magento\Framework\App\Action\Context $actionFlag, $view, $messageManager, - $resultRedirectFactory + $resultRedirectFactory, + $resultFactory ); $this->_session = $session; diff --git a/app/code/Magento/Backend/App/Config.php b/app/code/Magento/Backend/App/Config.php index d8eaa7af14254bd16dd3c8f7ae3cc9a549e75cde..0ac5211b41d9f58308d4f57977e0c8054c15e4c7 100644 --- a/app/code/Magento/Backend/App/Config.php +++ b/app/code/Magento/Backend/App/Config.php @@ -10,6 +10,8 @@ namespace Magento\Backend\App; +use Magento\Framework\App\Config\ScopeConfigInterface; + /** * Backend config accessor */ @@ -36,7 +38,7 @@ class Config implements ConfigInterface */ public function getValue($path) { - return $this->_scopePool->getScope(\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, null)->getValue($path); + return $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->getValue($path); } /** @@ -48,7 +50,7 @@ class Config implements ConfigInterface */ public function setValue($path, $value) { - $this->_scopePool->getScope(\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, null)->setValue($path, $value); + $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->setValue($path, $value); } /** @@ -59,6 +61,6 @@ class Config implements ConfigInterface */ public function isSetFlag($path) { - return !!$this->_scopePool->getScope(\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, null)->getValue($path); + return !!$this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->getValue($path); } } diff --git a/app/code/Magento/Backend/Block/Menu.php b/app/code/Magento/Backend/Block/Menu.php index 6eaed8e5b16344608d8b4672b933ca2b013c284d..087fd1fa351709778cc536f519c4b84206d97134 100644 --- a/app/code/Magento/Backend/Block/Menu.php +++ b/app/code/Magento/Backend/Block/Menu.php @@ -419,7 +419,7 @@ class Menu extends \Magento\Backend\Block\Template if ($level == 0 && $limit) { $colStops = $this->_columnBrake($menuItem->getChildren(), $limit); $output .= '<strong class="submenu-title">' . $this->_getAnchorLabel($menuItem) . '</strong>'; - $output .= '<a href="#" class="submenu-close _close" data-role="close-submenu"></a>'; + $output .= '<a href="#" class="action-close _close" data-role="close-submenu"></a>'; } $output .= $this->renderNavigation($menuItem->getChildren(), $level + 1, $limit, $colStops); @@ -436,6 +436,7 @@ class Menu extends \Magento\Backend\Block\Template * @param array $colBrakes * @return string HTML * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function renderNavigation($menu, $level = 0, $limit = 0, $colBrakes = []) { @@ -454,21 +455,30 @@ class Menu extends \Magento\Backend\Block\Template } $id = $this->getJsId($menuItem->getId()); - $output .= '<li ' . $this->getUiId( - $menuItem->getId() - ) . ' class="item-' . $itemClass . ' ' . $this->_renderItemCssClass( - $menuItem, - $level - ) . ($level == 0 ? '" id="' . $id . '" aria-haspopup="true' : '') - . '" role="menu-item">' . $this->_renderAnchor( - $menuItem, - $level - ) . $this->_addSubMenu( - $menuItem, - $level, - $limit, - $id - ) . '</li>'; + if (count($menu) > 1 || $level != 1) { + $output .= '<li ' . $this->getUiId( + $menuItem->getId() + ) . ' class="item-' . $itemClass . ' ' . $this->_renderItemCssClass( + $menuItem, + $level + ) . ($level == 0 ? '" id="' . $id . '" aria-haspopup="true' : '') + . '" role="menu-item">' . $this->_renderAnchor( + $menuItem, + $level + ) . $this->_addSubMenu( + $menuItem, + $level, + $limit, + $id + ) . '</li>'; + } else { + $output .= $this->_addSubMenu( + $menuItem, + $level, + $limit, + $id); + } + $itemPosition++; } diff --git a/app/code/Magento/Backend/Block/Page/System/Config/Robots/Reset.php b/app/code/Magento/Backend/Block/Page/System/Config/Robots/Reset.php index d32e99a00d814b5a134e9e3060526e7586f9043e..827ae18b0b8e1f908653597bc1816a6c73d9b148 100644 --- a/app/code/Magento/Backend/Block/Page/System/Config/Robots/Reset.php +++ b/app/code/Magento/Backend/Block/Page/System/Config/Robots/Reset.php @@ -8,6 +8,8 @@ namespace Magento\Backend\Block\Page\System\Config\Robots; +use Magento\Framework\App\Config\ScopeConfigInterface; + /** * "Reset to Defaults" button renderer * @@ -50,7 +52,7 @@ class Reset extends \Magento\Config\Block\System\Config\Form\Field public function getRobotsDefaultCustomInstructions() { return trim((string)$this->_scopeConfig->getValue( - self::XML_PATH_ROBOTS_DEFAULT_CUSTOM_INSTRUCTIONS, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + self::XML_PATH_ROBOTS_DEFAULT_CUSTOM_INSTRUCTIONS, ScopeConfigInterface::SCOPE_TYPE_DEFAULT )); } diff --git a/app/code/Magento/Backend/Block/Widget/Grid.php b/app/code/Magento/Backend/Block/Widget/Grid.php index 0e0ac51f859950b32f695e7014a04de1a7ce4684..1d33dc18146219f8fe4cb68d00b03a1aefa0ebad 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid.php +++ b/app/code/Magento/Backend/Block/Widget/Grid.php @@ -391,6 +391,10 @@ class Grid extends \Magento\Backend\Block\Widget */ protected function _prepareGrid() { + $this->_eventManager->dispatch( + 'backend_block_widget_grid_prepare_grid_before', + ['grid' => $this, 'collection' => $this->getCollection()] + ); if ($this->getChildBlock('grid.massaction') && $this->getChildBlock('grid.massaction')->isAvailable()) { $this->getChildBlock('grid.massaction')->prepareMassactionColumn(); } @@ -433,6 +437,10 @@ class Grid extends \Magento\Backend\Block\Widget 'Magento\Backend\Block\Widget\Button' )->setData( ['label' => __('Reset Filter'), 'onclick' => $this->getJsObjectName() . '.resetFilter()', 'class' => 'action-reset'] + )->setDataAttribute( + [ + 'action' => 'grid-filter-reset' + ] ) ); $this->setChild( @@ -445,6 +453,10 @@ class Grid extends \Magento\Backend\Block\Widget 'onclick' => $this->getJsObjectName() . '.doFilter()', 'class' => 'task', ] + )->setDataAttribute( + [ + 'action' => 'grid-filter-apply' + ] ) ); } diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Filter/Datetime.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Filter/Datetime.php index 4d5255c93cd4187907d0873697444b7d2203af2f..7ff6ce3773c50ef14917a85706ac5d8a0af4d02b 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Filter/Datetime.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Filter/Datetime.php @@ -104,7 +104,7 @@ class Datetime extends \Magento\Backend\Block\Widget\Grid\Column\Filter\Date $html = '<div class="range" id="' . $htmlId . '_range"><div class="range-line date">' . '<input type="text" name="' . $this->_getHtmlName() . '[from]" id="' . $htmlId . '_from"' . ' value="' . $this->getEscapedValue('from') - . '" class="input-text no-changes" placeholder="' . __( + . '" class="input-text admin__control-text no-changes" placeholder="' . __( 'From' ) . '" ' . $this->getUiId( 'filter', @@ -114,7 +114,7 @@ class Datetime extends \Magento\Backend\Block\Widget\Grid\Column\Filter\Date $html .= '<div class="range-line date">' . '<input type="text" name="' . $this->_getHtmlName() . '[to]" id="' . $htmlId . '_to"' . ' value="' . $this->getEscapedValue( 'to' - ) . '" class="input-text no-changes" placeholder="' . __( + ) . '" class="input-text admin__control-text no-changes" placeholder="' . __( 'To' ) . '" ' . $this->getUiId( 'filter', diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Extended.php b/app/code/Magento/Backend/Block/Widget/Grid/Extended.php index cafd687c9da150d6c0d56c7e0649645a24923e51..516c3eaae5040e655ac5bf02c7b2871a9208a394 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Extended.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Extended.php @@ -208,6 +208,10 @@ class Extended extends \Magento\Backend\Block\Widget\Grid implements \Magento\Ba 'onclick' => $this->getJsObjectName() . '.resetFilter()', 'class' => 'action-reset' ] + )->setDataAttribute( + [ + 'action' => 'grid-filter-reset' + ] ) ); $this->setChild( @@ -218,6 +222,10 @@ class Extended extends \Magento\Backend\Block\Widget\Grid implements \Magento\Ba 'onclick' => $this->getJsObjectName() . '.doFilter()', 'class' => 'task', ] + )->setDataAttribute( + [ + 'action' => 'grid-filter-apply' + ] ) ); return parent::_prepareLayout(); diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php index fec438f70c744d7b7cc9999d8574f3e4deef862c..d5cf7e86c4b8ae8c301a2993893a9d31d615e7e5 100644 --- a/app/code/Magento/Backend/Model/Auth/Session.php +++ b/app/code/Magento/Backend/Model/Auth/Session.php @@ -61,9 +61,11 @@ class Session extends \Magento\Framework\Session\SessionManager implements \Mage * @param \Magento\Framework\Session\StorageInterface $storage * @param CookieManagerInterface $cookieManager * @param CookieMetadataFactory $cookieMetadataFactory + * @param \Magento\Framework\App\State $appState * @param \Magento\Framework\Acl\Builder $aclBuilder * @param \Magento\Backend\Model\UrlInterface $backendUrl * @param \Magento\Backend\App\ConfigInterface $config + * @throws \Magento\Framework\Exception\SessionException * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -75,6 +77,7 @@ class Session extends \Magento\Framework\Session\SessionManager implements \Mage \Magento\Framework\Session\StorageInterface $storage, CookieManagerInterface $cookieManager, CookieMetadataFactory $cookieMetadataFactory, + \Magento\Framework\App\State $appState, \Magento\Framework\Acl\Builder $aclBuilder, \Magento\Backend\Model\UrlInterface $backendUrl, \Magento\Backend\App\ConfigInterface $config @@ -90,9 +93,9 @@ class Session extends \Magento\Framework\Session\SessionManager implements \Mage $validator, $storage, $cookieManager, - $cookieMetadataFactory + $cookieMetadataFactory, + $appState ); - $this->start(); } /** diff --git a/app/code/Magento/Backend/Model/Locale/Manager.php b/app/code/Magento/Backend/Model/Locale/Manager.php index 76a327f1364d1b42a05f3ea000474049d5b87068..4f9584c96a81706b0eaefafd3137a27d75291fc3 100644 --- a/app/code/Magento/Backend/Model/Locale/Manager.php +++ b/app/code/Magento/Backend/Model/Locale/Manager.php @@ -68,7 +68,7 @@ class Manager */ public function getUserInterfaceLocale() { - $interfaceLocale = \Magento\Framework\Locale\ResolverInterface::DEFAULT_LOCALE; + $interfaceLocale = \Magento\Framework\Locale\Resolver::DEFAULT_LOCALE; $userData = $this->_authSession->getUser(); if ($userData && $userData->getInterfaceLocale()) { diff --git a/app/code/Magento/Backend/Model/Session.php b/app/code/Magento/Backend/Model/Session.php index c0719bb2ecf9ef98084a0ecba7e11630732eddbf..6dd5af4a3c54830029f8372e214009a4e3b04bef 100644 --- a/app/code/Magento/Backend/Model/Session.php +++ b/app/code/Magento/Backend/Model/Session.php @@ -9,39 +9,6 @@ namespace Magento\Backend\Model; class Session extends \Magento\Framework\Session\SessionManager { - /** - * @param \Magento\Framework\App\Request\Http $request - * @param \Magento\Framework\Session\SidResolverInterface $sidResolver - * @param \Magento\Framework\Session\Config\ConfigInterface $sessionConfig - * @param \Magento\Framework\Session\SaveHandlerInterface $saveHandler - * @param \Magento\Framework\Session\ValidatorInterface $validator - * @param \Magento\Framework\Session\StorageInterface $storage - * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager - * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory - */ - public function __construct( - \Magento\Framework\App\Request\Http $request, - \Magento\Framework\Session\SidResolverInterface $sidResolver, - \Magento\Framework\Session\Config\ConfigInterface $sessionConfig, - \Magento\Framework\Session\SaveHandlerInterface $saveHandler, - \Magento\Framework\Session\ValidatorInterface $validator, - \Magento\Framework\Session\StorageInterface $storage, - \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, - \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory - ) { - parent::__construct( - $request, - $sidResolver, - $sessionConfig, - $saveHandler, - $validator, - $storage, - $cookieManager, - $cookieMetadataFactory - ); - $this->start(); - } - /** * Skip path validation in backend area * diff --git a/app/code/Magento/Backend/Model/Session/Quote.php b/app/code/Magento/Backend/Model/Session/Quote.php index 2f1f75ab07e9201d03ec0706fc3a0fb20f42ddc1..1427e1ad5ad570d5ea93c0f5cef3c5cdfd71c4cb 100644 --- a/app/code/Magento/Backend/Model/Session/Quote.php +++ b/app/code/Magento/Backend/Model/Session/Quote.php @@ -83,11 +83,13 @@ class Quote extends \Magento\Framework\Session\SessionManager * @param \Magento\Framework\Session\StorageInterface $storage * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory + * @param \Magento\Framework\App\State $appState * @param CustomerRepositoryInterface $customerRepository * @param \Magento\Quote\Model\QuoteRepository $quoteRepository * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param GroupManagementInterface $groupManagement + * @throws \Magento\Framework\Exception\SessionException * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -99,6 +101,7 @@ class Quote extends \Magento\Framework\Session\SessionManager \Magento\Framework\Session\StorageInterface $storage, \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory, + \Magento\Framework\App\State $appState, CustomerRepositoryInterface $customerRepository, \Magento\Quote\Model\QuoteRepository $quoteRepository, \Magento\Sales\Model\OrderFactory $orderFactory, @@ -118,9 +121,9 @@ class Quote extends \Magento\Framework\Session\SessionManager $validator, $storage, $cookieManager, - $cookieMetadataFactory + $cookieMetadataFactory, + $appState ); - $this->start(); if ($this->_storeManager->hasSingleStore()) { $this->setStoreId($this->_storeManager->getStore(true)->getId()); } @@ -147,7 +150,7 @@ class Quote extends \Magento\Framework\Session\SessionManager $this->_quote->setStoreId($this->getStoreId()); } - if ($this->getCustomerId()) { + if ($this->getCustomerId() && $this->getCustomerId() != $this->_quote->getCustomerId()) { $customer = $this->customerRepository->getById($this->getCustomerId()); $this->_quote->assignCustomer($customer); } diff --git a/app/code/Magento/Backend/Model/Url.php b/app/code/Magento/Backend/Model/Url.php index 265a7237ed37e1713fb17d97a3674c633d406341..36fbfafe66974d236c0bc90c2d7133fc3bcf128b 100644 --- a/app/code/Magento/Backend/Model/Url.php +++ b/app/code/Magento/Backend/Model/Url.php @@ -83,7 +83,7 @@ class Url extends \Magento\Framework\Url implements \Magento\Backend\Model\UrlIn * @param \Magento\Framework\Url\ScopeResolverInterface $scopeResolver * @param \Magento\Framework\Session\Generic $session * @param \Magento\Framework\Session\SidResolverInterface $sidResolver - * @param \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolver + * @param \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory * @param \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param string $scopeType @@ -105,7 +105,7 @@ class Url extends \Magento\Framework\Url implements \Magento\Backend\Model\UrlIn \Magento\Framework\Url\ScopeResolverInterface $scopeResolver, \Magento\Framework\Session\Generic $session, \Magento\Framework\Session\SidResolverInterface $sidResolver, - \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolver, + \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory, \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, $scopeType, @@ -126,7 +126,7 @@ class Url extends \Magento\Framework\Url implements \Magento\Backend\Model\UrlIn $scopeResolver, $session, $sidResolver, - $routeParamsResolver, + $routeParamsResolverFactory, $queryParamsResolver, $scopeConfig, $scopeType, diff --git a/app/code/Magento/Backend/Setup/ConfigOptionsList.php b/app/code/Magento/Backend/Setup/ConfigOptionsList.php index 83a953cd2f2232cc36e741682e95e3c406dfc194..4872cd18fe2099561e1b9bf5cb580ea43d756f56 100644 --- a/app/code/Magento/Backend/Setup/ConfigOptionsList.php +++ b/app/code/Magento/Backend/Setup/ConfigOptionsList.php @@ -19,7 +19,7 @@ class ConfigOptionsList implements ConfigOptionsListInterface /** * Input key for the options */ - const INPUT_KEY_BACKEND_FRONTNAME = 'backend_frontname'; + const INPUT_KEY_BACKEND_FRONTNAME = 'backend-frontname'; /** * Path to the values in the deployment config diff --git a/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php b/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php index 000c861f11d8eba4c098f8427df867287de61c2d..a624a526d5dbffd7dcd06460a11872fb1f4328c2 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/Locale/ManagerTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Backend\Test\Unit\Model\Locale; +use Magento\Framework\Locale\Resolver; + class ManagerTest extends \PHPUnit_Framework_TestCase { /** @@ -87,7 +89,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase { $locale = $this->_model->getUserInterfaceLocale(); - $this->assertEquals($locale, \Magento\Framework\Locale\ResolverInterface::DEFAULT_LOCALE); + $this->assertEquals($locale, Resolver::DEFAULT_LOCALE); } /** diff --git a/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php b/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php index 13f906bee346b45c02399d3f2cdc59602f9dec3f..fd3af3380023396c31f53ac97a41a1a631154993 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php @@ -182,6 +182,13 @@ class QuoteTest extends \PHPUnit_Framework_TestCase '', false ); + $appStateMock = $this->getMock( + 'Magento\Framework\App\State', + [], + [], + '', + false + ); $this->storeManagerMock = $this->getMockForAbstractClass( 'Magento\Store\Model\StoreManagerInterface', [], @@ -201,11 +208,12 @@ class QuoteTest extends \PHPUnit_Framework_TestCase 'storage' => $this->storageMock, 'cookieManager' => $this->cookieManagerMock, 'cookieMetadataFactory' => $this->cookieMetadataFactoryMock, + 'appState' => $appStateMock, 'customerRepository' => $this->customerRepositoryMock, 'quoteRepository' => $this->quoteRepositoryMock, 'orderFactory' => $this->orderFactoryMock, 'storeManager' => $this->storeManagerMock, - 'groupManagement' => $this->groupManagementMock + 'groupManagement' => $this->groupManagementMock, ], '', true @@ -217,12 +225,42 @@ class QuoteTest extends \PHPUnit_Framework_TestCase * * @return void */ - public function testGetQuote() + public function testGetQuoteWithoutQuoteId() { - $storeId = 10; $quoteId = 22; - $customerGroupId = 77; + $storeId = 10; $customerId = 66; + $customerGroupId = 77; + + $this->quote->expects($this->any()) + ->method('getQuoteId') + ->will($this->returnValue(null)); + $this->quote->expects($this->any()) + ->method('setQuoteId') + ->with($quoteId); + $this->quote->expects($this->any()) + ->method('getStoreId') + ->will($this->returnValue($storeId)); + $this->quote->expects($this->any()) + ->method('getCustomerId') + ->will($this->returnValue($customerId)); + + $defaultGroup = $this->getMockBuilder('Magento\Customer\Api\Data\GroupInterface') + ->getMock(); + $defaultGroup->expects($this->any()) + ->method('getId') + ->will($this->returnValue($customerGroupId)); + $this->groupManagementMock->expects($this->any()) + ->method('getDefaultGroup') + ->will($this->returnValue($defaultGroup)); + + $dataCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->customerRepositoryMock->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($dataCustomerMock); $quoteMock = $this->getMock( 'Magento\Quote\Model\Quote', @@ -240,28 +278,9 @@ class QuoteTest extends \PHPUnit_Framework_TestCase '', false ); - - $defaultGroup = $this->getMockBuilder('Magento\Customer\Api\Data\GroupInterface') - ->getMock(); - $defaultGroup->expects($this->any()) - ->method('getId') - ->will($this->returnValue($customerGroupId)); - $this->groupManagementMock->expects($this->any()) - ->method('getDefaultGroup') - ->will($this->returnValue($defaultGroup)); - - $this->quoteRepositoryMock->expects($this->once()) - ->method('create') - ->will($this->returnValue($quoteMock)); - $this->quote->expects($this->any()) - ->method('getStoreId') - ->will($this->returnValue($storeId)); $quoteMock->expects($this->once()) ->method('setStoreId') ->with($storeId); - $this->quote->expects($this->any()) - ->method('getQuoteId') - ->will($this->returnValue(null)); $quoteMock->expects($this->once()) ->method('setCustomerGroupId') ->with($customerGroupId) @@ -270,25 +289,9 @@ class QuoteTest extends \PHPUnit_Framework_TestCase ->method('setIsActive') ->with(false) ->will($this->returnSelf()); - $this->quoteRepositoryMock->expects($this->once()) - ->method('save') - ->with($quoteMock); $quoteMock->expects($this->once()) ->method('getId') ->will($this->returnValue($quoteId)); - $this->quote->expects($this->any()) - ->method('setQuoteId') - ->with($quoteId); - $this->quote->expects($this->any()) - ->method('getCustomerId') - ->will($this->returnValue($customerId)); - $dataCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->disableOriginalConstructor() - ->getMock(); - $this->customerRepositoryMock->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($dataCustomerMock); $quoteMock->expects($this->once()) ->method('assignCustomer') ->with($dataCustomerMock); @@ -299,6 +302,13 @@ class QuoteTest extends \PHPUnit_Framework_TestCase ->method('setIsSuperMode') ->with(true); + $this->quoteRepositoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($quoteMock)); + $this->quoteRepositoryMock->expects($this->once()) + ->method('save') + ->with($quoteMock); + $this->assertEquals($quoteMock, $this->quote->getQuote()); } @@ -306,12 +316,33 @@ class QuoteTest extends \PHPUnit_Framework_TestCase * Run test getQuote method * * @return void + * @dataProvider getQuoteDataProvider */ - public function testGetQuoteGet() + public function testGetQuoteWithQuoteId($customerId, $quoteCustomerId, $expectedNumberOfInvokes) { - $storeId = 10; $quoteId = 22; - $customerId = 66; + $storeId = 10; + + $this->quote->expects($this->any()) + ->method('getQuoteId') + ->will($this->returnValue($quoteId)); + $this->quote->expects($this->any()) + ->method('setQuoteId') + ->with($quoteId); + $this->quote->expects($this->any()) + ->method('getStoreId') + ->will($this->returnValue($storeId)); + $this->quote->expects($this->any()) + ->method('getCustomerId') + ->will($this->returnValue($customerId)); + + $dataCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->customerRepositoryMock->expects($this->$expectedNumberOfInvokes()) + ->method('getById') + ->with($customerId) + ->willReturn($dataCustomerMock); $quoteMock = $this->getMock( 'Magento\Quote\Model\Quote', @@ -323,43 +354,17 @@ class QuoteTest extends \PHPUnit_Framework_TestCase 'assignCustomer', 'setIgnoreOldQty', 'setIsSuperMode', + 'getCustomerId', '__wakeup' ], [], '', false ); - - $this->quoteRepositoryMock->expects($this->once()) - ->method('create') - ->will($this->returnValue($quoteMock)); - $this->quote->expects($this->any()) - ->method('getStoreId') - ->will($this->returnValue($storeId)); $quoteMock->expects($this->once()) ->method('setStoreId') ->with($storeId); - $this->quote->expects($this->any()) - ->method('getQuoteId') - ->will($this->returnValue($quoteId)); - $this->quoteRepositoryMock->expects($this->once()) - ->method('get') - ->with($quoteId) - ->willReturn($quoteMock); - $this->quote->expects($this->any()) - ->method('setQuoteId') - ->with($quoteId); - $this->quote->expects($this->any()) - ->method('getCustomerId') - ->will($this->returnValue($customerId)); - $dataCustomerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') - ->disableOriginalConstructor() - ->getMock(); - $this->customerRepositoryMock->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($dataCustomerMock); - $quoteMock->expects($this->once()) + $quoteMock->expects($this->$expectedNumberOfInvokes()) ->method('assignCustomer') ->with($dataCustomerMock); $quoteMock->expects($this->once()) @@ -368,7 +373,29 @@ class QuoteTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->once()) ->method('setIsSuperMode') ->with(true); + $quoteMock->expects($this->once()) + ->method('getCustomerId') + ->will($this->returnValue($quoteCustomerId)); + + $this->quoteRepositoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($quoteMock)); + $this->quoteRepositoryMock->expects($this->once()) + ->method('get') + ->with($quoteId) + ->willReturn($quoteMock); $this->assertEquals($quoteMock, $this->quote->getQuote()); } + + /** + * @return array + */ + public function getQuoteDataProvider() + { + return [ + 'customer ids different' => [66, null, 'once'], + 'customer ids same' => [66, 66, 'never'], + ]; + } } diff --git a/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php b/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php index a53b891a17be5e100f0916cf04e6b2a4f3469c71..b833fe25752a09ecd9af87a7147f4debf493affe 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php @@ -165,7 +165,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase 'menuConfig' => $this->_menuConfigMock, 'authSession' => $this->_authSessionMock, 'encryptor' => $this->_encryptor, - 'routeParamsResolver' => $this->_paramsResolverMock + 'routeParamsResolverFactory' => $this->_paramsResolverMock ] ); $this->_paramsResolverMock->expects( @@ -186,7 +186,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase 'menuConfig' => $this->_menuConfigMock, 'authSession' => $this->_authSessionMock, 'encryptor' => $this->_encryptor, - 'routeParamsResolver' => $this->_paramsResolverMock + 'routeParamsResolverFactory' => $this->_paramsResolverMock ] ); @@ -259,7 +259,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase [ 'backendHelper' => $helperMock, 'authSession' => $this->_authSessionMock, - 'routeParamsResolver' => $this->_paramsResolverMock + 'routeParamsResolverFactory' => $this->_paramsResolverMock ] ); $urlModel->getAreaFrontName(); diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json index d229a7feb44b54367af4b052d1c43bc2a8f7e517..d304a64899593b2b01303dd3e431a9c59fb47fbc 100644 --- a/app/code/Magento/Backend/composer.json +++ b/app/code/Magento/Backend/composer.json @@ -3,27 +3,27 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-developer": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-cron": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-reports": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-user": "0.74.0-beta6", - "magento/module-backup": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-translation": "0.74.0-beta6", - "magento/module-require-js": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-developer": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-cron": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-reports": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-user": "0.74.0-beta7", + "magento/module-backup": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-translation": "0.74.0-beta7", + "magento/module-require-js": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Backend/etc/adminhtml/di.xml b/app/code/Magento/Backend/etc/adminhtml/di.xml index ba52677a683d9ee8e098cdd48bda87ddc128c2e9..553d30e85541f36dbd0a50834d1d146d99b84d5d 100644 --- a/app/code/Magento/Backend/etc/adminhtml/di.xml +++ b/app/code/Magento/Backend/etc/adminhtml/di.xml @@ -90,6 +90,24 @@ <argument name="instanceName" xsi:type="string">Magento\Backend\Model\View\Result\Page</argument> </arguments> </type> + <type name="Magento\Framework\Controller\ResultFactory"> + <arguments> + <argument name="typeMap" xsi:type="array"> + <item name="redirect" xsi:type="array"> + <item name="type" xsi:type="const">Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT</item> + <item name="class" xsi:type="string">Magento\Backend\Model\View\Result\Redirect</item> + </item> + <item name="page" xsi:type="array"> + <item name="type" xsi:type="const">Magento\Framework\Controller\ResultFactory::TYPE_PAGE</item> + <item name="class" xsi:type="string">Magento\Backend\Model\View\Result\Page</item> + </item> + <item name="forward" xsi:type="array"> + <item name="type" xsi:type="const">Magento\Framework\Controller\ResultFactory::TYPE_FORWARD</item> + <item name="class" xsi:type="string">Magento\Backend\Model\View\Result\Forward</item> + </item> + </argument> + </arguments> + </type> <type name="Magento\Framework\View\Layout\BuilderFactory"> <arguments> <argument name="typeMap" xsi:type="array"> diff --git a/app/code/Magento/Backend/view/adminhtml/templates/admin/login.phtml b/app/code/Magento/Backend/view/adminhtml/templates/admin/login.phtml index 1d1cb81fd064a8dce77e3e6b76b8675672293118..12d8f0b32e94d50d64a55d9b687b84492af28c20 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/admin/login.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/admin/login.phtml @@ -7,6 +7,7 @@ // @codingStandardsIgnoreFile ?> + <form method="post" action="" id="login-form" data-mage-init='{"form": {}, "validation": {}}' autocomplete="off"> <fieldset class="admin__fieldset"> <legend class="admin__legend"><span><?php echo __('Welcome, please sign in') ?></span></legend><br/> @@ -14,15 +15,33 @@ <div class="admin__field _required field-username"> <label for="username" class="admin__field-label"><span><?php echo __('Username') ?></span></label> <div class="admin__field-control"> - <input type="text" id="username" name="login[username]" autofocus value="" data-validate="{required:true}" class="admin__control-text" placeholder="<?php echo __('user name') ?>" /> + <input + id="username" + class="admin__control-text" + type="text" + name="login[username]" + autofocus + value="" + data-validate="{required:true}" + placeholder="<?php echo __('user name') ?>"/> </div> </div> <div class="admin__field _required field-password"> <label for="login" class="admin__field-label"><span><?php echo __('Password') ?></span></label> <div class="admin__field-control"> <!-- This is a dummy hidden field to trick firefox from auto filling the password --> - <input type="text" class="admin__control-dummy" name="dummy" id="dummy" /> - <input type="password" id="login" name="login[password]" data-validate="{required:true}" class="admin__control-text" value="" placeholder="<?php echo __('password') ?>" /> + <input + id="dummy" + class="admin__control-dummy" + type="text" + name="dummy"/> + <input + id="login" + class="admin__control-text" + type="password" + name="login[password]" + data-validate="{required:true}" + value="" placeholder="<?php echo __('password') ?>" /> </div> </div> <?php echo $block->getChildHtml('form.additional.info'); ?> diff --git a/app/code/Magento/Backend/view/adminhtml/templates/dashboard/grid.phtml b/app/code/Magento/Backend/view/adminhtml/templates/dashboard/grid.phtml index 78d3d2677e94c705cc86af43d9562ff37aaacc6f..e9a724fdbf857b838c893142f1cd7c88e8276af3 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/dashboard/grid.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/dashboard/grid.phtml @@ -14,7 +14,7 @@ $numColumns = sizeof($block->getColumns()); <?php if ($block->getCollection()): ?> <div class="dashboard-item-content"> <?php if ($block->getCollection()->getSize()>0): ?> - <table class="table-info dashboard-data" id="<?php echo $block->getId() ?>_table"> + <table class="admin__table-primary dashboard-data" id="<?php echo $block->getId() ?>_table"> <?php /* This part is commented to remove all <col> tags from the code. */ /* foreach ($block->getColumns() as $_column): ?> diff --git a/app/code/Magento/Backend/view/adminhtml/templates/page/header.phtml b/app/code/Magento/Backend/view/adminhtml/templates/page/header.phtml index 6e90069f9ee6c87bfcc4119b16c78d46ecfd3583..8b60043de0f8d49b63f65ab771eef3a065fcfec6 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/page/header.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/page/header.phtml @@ -21,18 +21,18 @@ </a> <?php break; ?> <?php case 'user': ?> - <div class="admin-user"> + <div class="admin-user admin__action-dropdown-wrap"> <a href="<?php echo $block->getUrl('adminhtml/system_account/index') ?>" - class="admin-user-account" + class="admin__action-dropdown" title="<?php echo $block->escapeHtml(__('My Account')) ?>" data-mage-init='{"dropdown":{}}' data-toggle="dropdown"> - <span class="admin-user-account-text-wrapper"> + <span class="admin__action-dropdown-text"> <span class="admin-user-account-text"><?php echo $block->escapeHtml($block->getUser()->getUsername()); ?></span> </span> </a> - <ul class="admin-user-menu"> + <ul class="admin__action-dropdown-menu"> <?php if ($block->getAuthorization()->isAllowed('Magento_Backend::myaccount')): ?> <li> <a diff --git a/app/code/Magento/Backup/README.md b/app/code/Magento/Backup/README.md index 661f8a5d6ddd86f23772c9f595526420ae51dd9e..59688ea3e716e162e8efa9421de0ffe004ec3cee 100644 --- a/app/code/Magento/Backup/README.md +++ b/app/code/Magento/Backup/README.md @@ -1,3 +1,3 @@ The Backup module allows administrators to perform backups and rollbacks. Types of backups include system, database and media backups. This module relies on the Cron module to schedule backups. -This module does not effect the storefront. \ No newline at end of file +This module does not affect the storefront. diff --git a/app/code/Magento/Backup/composer.json b/app/code/Magento/Backup/composer.json index f7f9a0371534346f0bc39f7d7087a12200428386..e562c51a28780fef47745fed5db8c70162f3417a 100644 --- a/app/code/Magento/Backup/composer.json +++ b/app/code/Magento/Backup/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-cron": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-cron": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml index 861bc2050e44a61e3cf1daf950dcad8fc05d0997..1553a783f6356dca8510044813cd919312ff5fdb 100644 --- a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml +++ b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_block.xml @@ -46,7 +46,6 @@ <arguments> <argument name="header" xsi:type="string" translate="true">Name</argument> <argument name="index" xsi:type="string">display_name</argument> - <argument name="filter" xsi:type="string">0</argument> <argument name="sortable" xsi:type="string">1</argument> <argument name="column_css_class" xsi:type="string">col-name</argument> <argument name="header_css_class" xsi:type="string">col-name</argument> diff --git a/app/code/Magento/Bundle/composer.json b/app/code/Magento/Bundle/composer.json index a16b4ad6d56cfb1002fae21f984ace5e9a5ea588..07f3110b0c936a3d3a3cdfac5dcf640aaf6b7c1e 100644 --- a/app/code/Magento/Bundle/composer.json +++ b/app/code/Magento/Bundle/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-catalog-rule": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-gift-message": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-catalog-rule": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-gift-message": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-webapi": "0.74.0-beta6" + "magento/module-webapi": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Bundle/etc/data_object.xml b/app/code/Magento/Bundle/etc/service_data_attributes.xml similarity index 70% rename from app/code/Magento/Bundle/etc/data_object.xml rename to app/code/Magento/Bundle/etc/service_data_attributes.xml index 2b3da013978f971bb20baca3a5e0ca95f2b501fc..8150a2dceeddd7d70d4e16ffa3d1b6996f316d5d 100644 --- a/app/code/Magento/Bundle/etc/data_object.xml +++ b/app/code/Magento/Bundle/etc/service_data_attributes.xml @@ -5,8 +5,8 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Catalog\Api\Data\ProductInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="bundle_product_options" type="Magento\Bundle\Api\Data\OptionInterface[]" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml index 73d5d50ee6574c39c785bb19b5c59977faf7d54c..c1f89d31bf4b7f5373a4538aa402470328621606 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml @@ -11,7 +11,8 @@ <?php /* @var $block \Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Bundle */ ?> <?php $options = $block->decorateArray($block->getOptions()); ?> <?php if (count($options)): ?> -<fieldset id="catalog_product_composite_configure_fields_bundle" class="fieldset admin__fieldset composite-bundle <?php echo $block->getIsLastFieldset() ? ' last-fieldset' : '' ?>"> +<fieldset id="catalog_product_composite_configure_fields_bundle" + class="fieldset admin__fieldset composite-bundle<?php echo $block->getIsLastFieldset() ? ' last-fieldset' : '' ?>"> <legend class="legend admin__legend"><span><?php echo __('Bundle Items') ?></span></legend><br /> <?php foreach ($options as $option) : ?> <?php if ($option->getSelections()) : ?> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/create/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/create/items/renderer.phtml index 6986d5ab2953413e6dc7d7ae5a3bd3c168f834f7..1179737cea667d6e059ea35b4add49db3264d4a2 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/create/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/create/items/renderer.phtml @@ -50,8 +50,8 @@ <?php if (!$_item->getOrderItem()->getParentItem()): ?> <td class="col-product"> <div class="product-title"><?php echo $block->escapeHtml($_item->getName()) ?></div> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> </td> @@ -67,46 +67,46 @@ </td> <td class="col-ordered-qty"> <?php if ($block->canShowPriceInfo($_item)): ?> - <table cellspacing="0" class="qty-table"> + <table class="data-table qty-table"> <tr> - <td><?php echo __('Ordered') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyOrdered()*1 ?></strong></td> + <th><?php echo __('Ordered') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyOrdered()*1 ?></td> </tr> <?php if ((float) $_item->getOrderItem()->getQtyInvoiced()): ?> <tr> - <td><?php echo __('Invoiced') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyInvoiced()*1 ?></strong></td> + <th><?php echo __('Invoiced') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyInvoiced()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getOrderItem()->getQtyShipped() && $block->isShipmentSeparately($_item)): ?> <tr> - <td><?php echo __('Shipped') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></strong></td> + <th><?php echo __('Shipped') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getOrderItem()->getQtyRefunded()): ?> <tr> - <td><?php echo __('Refunded') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyRefunded()*1 ?></strong></td> + <th><?php echo __('Refunded') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyRefunded()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getOrderItem()->getQtyCanceled()): ?> <tr> - <td><?php echo __('Canceled') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyCanceled()*1 ?></strong></td> + <th><?php echo __('Canceled') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyCanceled()*1 ?></td> </tr> <?php endif; ?> </table> <?php elseif ($block->isShipmentSeparately($_item)): ?> - <table cellspacing="0" class="qty-table"> + <table class="data-table qty-table"> <tr> - <td><?php echo __('Ordered') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyOrdered()*1 ?></strong></td> + <th><?php echo __('Ordered') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyOrdered()*1 ?></td> </tr> <?php if ((float) $_item->getOrderItem()->getQtyShipped()): ?> <tr> - <td><?php echo __('Shipped') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></strong></td> + <th><?php echo __('Shipped') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></td> </tr> <?php endif; ?> </table> @@ -118,17 +118,24 @@ <td class="col-return-to-stock"> <?php if ($block->canShowPriceInfo($_item)): ?> <?php if ($block->canReturnItemToStock($_item)) : ?> - <input type="checkbox" name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][back_to_stock]" value="1"<?php if ($_item->getBackToStock()):?> checked="checked"<?php endif;?> /> + <input type="checkbox" + class="admin__control-checkbox" + name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][back_to_stock]" + value="1"<?php if ($_item->getBackToStock()):?> checked="checked"<?php endif;?> /> + <label class="admin__field-label"></label> <?php endif; ?> <?php else: ?> <?php endif; ?> </td> <?php endif; ?> - <td class="col-refund"> + <td class="col-refund col-qty"> <?php if ($block->canShowPriceInfo($_item)): ?> <?php if ($block->canEditQty()) : ?> - <input type="text" class="input-text qty-input" name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][qty]" value="<?php echo $_item->getQty()*1 ?>" /> + <input type="text" + class="input-text admin__control-text qty-input" + name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][qty]" + value="<?php echo $_item->getQty()*1 ?>" /> <?php else: ?> <?php echo $_item->getQty()*1 ?> <?php endif; ?> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/view/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/view/items/renderer.phtml index 37b22d2d43a2b046b225e2a2b247efc230ac5663..339bc32af067a91741ffcf2945265f7696177ecd 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/view/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/creditmemo/view/items/renderer.phtml @@ -48,8 +48,8 @@ <?php if (!$_item->getOrderItem()->getParentItem()): ?> <td class="col-product"> <div class="product-title"><?php echo $block->escapeHtml($_item->getName()) ?></div> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> </td> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml index 5ad5c664845271785c65c01e01aa961591b6c333..ffabb6efc13ddf417d9fccb35aacdbec50099598 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml @@ -49,8 +49,8 @@ <?php if (!$_item->getOrderItem()->getParentItem()): ?> <td class="col-product"> <div class="product-title"><?php echo $block->escapeHtml($_item->getName()) ?></div> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> </td> @@ -68,46 +68,46 @@ </td> <td class="col-qty"> <?php if ($block->canShowPriceInfo($_item)): ?> - <table cellspacing="0" class="qty-table"> + <table class="data-table qty-table"> <tr> - <td><?php echo __('Ordered') ?></td> + <th><?php echo __('Ordered') ?></th> <td><strong><?php echo $_item->getOrderItem()->getQtyOrdered()*1 ?></strong></td> </tr> <?php if ((float) $_item->getOrderItem()->getQtyInvoiced()): ?> <tr> - <td><?php echo __('Invoiced') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyInvoiced()*1 ?></strong></td> + <th><?php echo __('Invoiced') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyInvoiced()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getOrderItem()->getQtyShipped() && $block->isShipmentSeparately($_item)): ?> <tr> - <td><?php echo __('Shipped') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></strong></td> + <th><?php echo __('Shipped') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getOrderItem()->getQtyRefunded()): ?> <tr> - <td><?php echo __('Refunded') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyRefunded()*1 ?></strong></td> + <th><?php echo __('Refunded') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyRefunded()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getOrderItem()->getQtyCanceled()): ?> <tr> - <td><?php echo __('Canceled') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyCanceled()*1 ?></strong></td> + <th><?php echo __('Canceled') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyCanceled()*1 ?></td> </tr> <?php endif; ?> </table> <?php elseif ($block->isShipmentSeparately($_item)): ?> - <table cellspacing="0" class="qty-table"> + <table class="data-table qty-table"> <tr> - <td><?php echo __('Ordered') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyOrdered()*1 ?></strong></td> + <th><?php echo __('Ordered') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyOrdered()*1 ?></td> </tr> <?php if ((float) $_item->getOrderItem()->getQtyShipped()): ?> <tr> - <td><?php echo __('Shipped') ?></td> - <td><strong><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></strong></td> + <th><?php echo __('Shipped') ?></th> + <td><?php echo $_item->getOrderItem()->getQtyShipped()*1 ?></td> </tr> <?php endif; ?> </table> @@ -118,7 +118,10 @@ <td class="col-qty-invoice"> <?php if ($block->canShowPriceInfo($_item)): ?> <?php if ($block->canEditQty()) : ?> - <input type="text" class="input-text qty-input" name="invoice[items][<?php echo $_item->getOrderItemId() ?>]" value="<?php echo $_item->getQty()*1 ?>" /> + <input type="text" + class="input-text admin__control-text qty-input" + name="invoice[items][<?php echo $_item->getOrderItemId() ?>]" + value="<?php echo $_item->getQty()*1 ?>" /> <?php else : ?> <?php echo $_item->getQty()*1 ?> <?php endif; ?> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/view/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/view/items/renderer.phtml index 33db5d905cf3acebb353d935c8665e76c5f455fc..904d804580feace61ab761f2daaf284fc712b64c 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/view/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/view/items/renderer.phtml @@ -48,8 +48,8 @@ <?php if (!$_item->getOrderItem()->getParentItem()): ?> <td class="col-product"> <div class="product-title"><?php echo $block->escapeHtml($_item->getName()) ?></div> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> <?php else: ?> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml index 8c89a6e27c5cf1c22168dd930127ad3efb3d97c5..2f31655de1e2eaa36a24aeb73c80812725ba71e0 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/order/view/items/renderer.phtml @@ -53,8 +53,8 @@ <div class="product-title" id="order_item_<?php echo $_item->getId() ?>_title"> <?php echo $block->escapeHtml($_item->getName()) ?> </div> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> </td> @@ -86,46 +86,46 @@ </td> <td class="col-ordered-qty"> <?php if ($block->canShowPriceInfo($_item)): ?> - <table cellspacing="0" class="qty-table"> + <table class="data-table qty-table"> <tr> - <td><?php echo __('Ordered') ?></td> - <td><strong><?php echo $_item->getQtyOrdered()*1 ?></strong></td> + <th><?php echo __('Ordered') ?></th> + <td><?php echo $_item->getQtyOrdered()*1 ?></td> </tr> <?php if ((float) $_item->getQtyInvoiced()): ?> <tr> - <td><?php echo __('Invoiced') ?></td> - <td><strong><?php echo $_item->getQtyInvoiced()*1 ?></strong></td> + <th><?php echo __('Invoiced') ?></th> + <td><?php echo $_item->getQtyInvoiced()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getQtyShipped() && $block->isShipmentSeparately($_item)): ?> <tr> - <td><?php echo __('Shipped') ?></td> - <td><strong><?php echo $_item->getQtyShipped()*1 ?></strong></td> + <th><?php echo __('Shipped') ?></th> + <td><?php echo $_item->getQtyShipped()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getQtyRefunded()): ?> <tr> - <td><?php echo __('Refunded') ?></td> - <td><strong><?php echo $_item->getQtyRefunded()*1 ?></strong></td> + <th><?php echo __('Refunded') ?></th> + <td><?php echo $_item->getQtyRefunded()*1 ?></td> </tr> <?php endif; ?> <?php if ((float) $_item->getQtyCanceled()): ?> <tr> - <td><?php echo __('Canceled') ?></td> - <td><strong><?php echo $_item->getQtyCanceled()*1 ?></strong></td> + <th><?php echo __('Canceled') ?></th> + <td><?php echo $_item->getQtyCanceled()*1 ?></td> </tr> <?php endif; ?> </table> <?php elseif ($block->isShipmentSeparately($_item)): ?> - <table cellspacing="0" class="qty-table"> + <table class="data-table qty-table"> <tr> - <td><?php echo __('Ordered') ?></td> - <td><strong><?php echo $_item->getQtyOrdered()*1 ?></strong></td> + <th><?php echo __('Ordered') ?></th> + <td><?php echo $_item->getQtyOrdered()*1 ?></td> </tr> <?php if ((float) $_item->getQtyShipped()): ?> <tr> - <td><?php echo __('Shipped') ?></td> - <td><strong><?php echo $_item->getQtyShipped()*1 ?></strong></td> + <th><?php echo __('Shipped') ?></th> + <td><?php echo $_item->getQtyShipped()*1 ?></td> </tr> <?php endif; ?> </table> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/create/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/create/items/renderer.phtml index 08ef77d9161508a2601fe4ff14fb2ae2ab093e98..f1555682244ee4ba68b1d7e6202f2d9b66f884bc 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/create/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/create/items/renderer.phtml @@ -43,8 +43,8 @@ <?php if (!$_item->getOrderItem()->getParentItem()): ?> <td class="col-product"> <div class="product-title"><?php echo $block->escapeHtml($_item->getName()) ?></div> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> </td> @@ -60,7 +60,10 @@ </td> <td class="col-qty last"> <?php if ($block->isShipmentSeparately($_item)): ?> - <input type="text" class="input-text" name="shipment[items][<?php echo $_item->getOrderItemId() ?>]" value="<?php echo $_item->getQty()*1 ?>" /> + <input type="text" + class="input-text admin__control-text" + name="shipment[items][<?php echo $_item->getOrderItemId() ?>]" + value="<?php echo $_item->getQty()*1 ?>" /> <?php else: ?> <?php endif; ?> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/view/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/view/items/renderer.phtml index 16c98a2522059be6648f1c36364584dca4a26ac7..e8a2d69f16530de18698e5808cc57591fb420bb2 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/view/items/renderer.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/shipment/view/items/renderer.phtml @@ -43,8 +43,8 @@ <?php if (!$_item->getParentItem()): ?> <td class="col-product"> <div class="product-title"><?php echo $block->escapeHtml($_item->getName()) ?></div> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> </td> diff --git a/app/code/Magento/CacheInvalidate/composer.json b/app/code/Magento/CacheInvalidate/composer.json index 4e1062c5a74902db562b9e2c7ed010ff9ab5bdfa..31eb21d58f55a24acfd34f0b5ca9623adead22f0 100644 --- a/app/code/Magento/CacheInvalidate/composer.json +++ b/app/code/Magento/CacheInvalidate/composer.json @@ -3,12 +3,12 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-page-cache": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-page-cache": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Captcha/composer.json b/app/code/Magento/Captcha/composer.json index dee103fd89226bade4029e318d5b99fd03bf2b30..d1ee6a69a432e98b832400e6b8bd3143bb7531cb 100644 --- a/app/code/Magento/Captcha/composer.json +++ b/app/code/Magento/Captcha/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml b/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml index d862e010441d261c1f906fc79dc8f28a9db1de57..d8811b0a29338951f610ca182a481d368745f3de 100644 --- a/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml +++ b/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml @@ -11,9 +11,16 @@ <?php /* @var $block \Magento\Captcha\Block\Captcha\DefaultCaptcha */ ?> <?php $captcha = $block->getCaptchaModel() ?> <div class="admin__field _required"> - <label for="captcha" class="admin__field-label"><span><?php echo __('Please enter the letters from the image') ?></span></label> + <label for="captcha" class="admin__field-label"> + <span><?php echo __('Please enter the letters from the image') ?></span> + </label> <div class="admin__field-control"> - <input type="text" name="<?php echo \Magento\Captcha\Helper\Data::INPUT_NAME_FIELD_VALUE ?>[<?php echo $block->getFormId()?>]" id="captcha" data-validate="{required:true}" class="admin__control-text"/> + <input + id="captcha" + class="admin__control-text" + type="text" + name="<?php echo \Magento\Captcha\Helper\Data::INPUT_NAME_FIELD_VALUE ?>[<?php echo $block->getFormId()?>]" + data-validate="{required:true}"/> <?php if ($captcha->isCaseSensitive()) :?> <div class="admin__field-note"> <span><?php echo __('<strong>Attention</strong>: Captcha is case sensitive.') ?></span> @@ -22,8 +29,16 @@ </div> </div> <div class="admin__field field-captcha"> - <img id="captcha-reload" class="captcha-reload" src="<?php echo $block->getViewFileUrl('Magento_Captcha::reload.png') ?>" alt="<?php echo __('Reload captcha') ?>"/> - <img id="<?php echo $block->getFormId() ?>" width="<?php echo $block->getImgWidth() ?>" height="<?php echo $block->getImgHeight() ?>" src="<?php echo $captcha->getImgSrc() ?>" /> + <img + id="captcha-reload" + class="captcha-reload" + src="<?php echo $block->getViewFileUrl('Magento_Captcha::reload.png') ?>" + alt="<?php echo __('Reload captcha') ?>"/> + <img + id="<?php echo $block->getFormId() ?>" + width="<?php echo $block->getImgWidth() ?>" + height="<?php echo $block->getImgHeight() ?>" + src="<?php echo $captcha->getImgSrc() ?>" /> </div> <script> require(["prototype", "mage/captcha"], function(){ diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php b/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php index a79466c6007bfb13a619d59a922c29d99d947968..29be0868558ee450d152d492091f5cb5b9bbaef8 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php @@ -29,7 +29,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template * * @var array */ - protected $_availableOrder = []; + protected $_availableOrder = null; /** * List of available view types @@ -146,19 +146,6 @@ class Toolbar extends \Magento\Framework\View\Element\Template parent::__construct($context, $data); } - /** - * Init Toolbar - * - * @return null - */ - protected function _construct() - { - parent::_construct(); - $this->_orderField = $this->_productListHelper->getDefaultSortField(); - $this->_availableOrder = $this->_catalogConfig->getAttributeUsedForSortByArray(); - $this->_availableMode = $this->_productListHelper->getAvailableViewMode(); - } - /** * Disable list state params memorizing * @@ -241,7 +228,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template } $orders = $this->getAvailableOrders(); - $defaultOrder = $this->_orderField; + $defaultOrder = $this->getOrderField(); if (!isset($orders[$defaultOrder])) { $keys = array_keys($orders); @@ -295,6 +282,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template */ public function setDefaultOrder($field) { + $this->loadAvailableOrders(); if (isset($this->_availableOrder[$field])) { $this->_orderField = $field; } @@ -322,6 +310,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template */ public function getAvailableOrders() { + $this->loadAvailableOrders(); return $this->_availableOrder; } @@ -346,6 +335,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template */ public function addOrderToAvailableOrders($order, $value) { + $this->loadAvailableOrders(); $this->_availableOrder[$order] = $value; return $this; } @@ -358,6 +348,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template */ public function removeOrderFromAvailableOrders($order) { + $this->loadAvailableOrders(); if (isset($this->_availableOrder[$order])) { unset($this->_availableOrder[$order]); } @@ -411,7 +402,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template if ($mode) { return $mode; } - $defaultMode = $this->_productListHelper->getDefaultViewMode($this->_availableMode); + $defaultMode = $this->_productListHelper->getDefaultViewMode($this->getModes()); $mode = $this->_toolbarModel->getMode(); if (!$mode || !isset($this->_availableMode[$mode])) { $mode = $defaultMode; @@ -439,6 +430,9 @@ class Toolbar extends \Magento\Framework\View\Element\Template */ public function getModes() { + if ($this->_availableMode === []) { + $this->_availableMode = $this->_productListHelper->getAvailableViewMode(); + } return $this->_availableMode; } @@ -450,6 +444,7 @@ class Toolbar extends \Magento\Framework\View\Element\Template */ public function setModes($modes) { + $this->getModes(); if (!isset($this->_availableMode)) { $this->_availableMode = $modes; } @@ -691,4 +686,30 @@ class Toolbar extends \Magento\Framework\View\Element\Template $options = array_replace_recursive($options, $customOptions); return json_encode(['productListToolbarForm' => $options]); } + + /** + * Get order field + * + * @return null|string + */ + protected function getOrderField() + { + if ($this->_orderField === null) { + $this->_orderField = $this->_productListHelper->getDefaultSortField(); + } + return $this->_orderField; + } + + /** + * Load Available Orders + * + * @return $this + */ + private function loadAvailableOrders() + { + if ($this->_availableOrder === null) { + $this->_availableOrder = $this->_catalogConfig->getAttributeUsedForSortByArray(); + } + return $this; + } } diff --git a/app/code/Magento/Catalog/Block/Product/View/Options.php b/app/code/Magento/Catalog/Block/Product/View/Options.php index f80bdede71af34f4440d8cce9ff14da2ebfdf9f0..db3d2a911038295fbcb8942d7c61f0041a2637a5 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Options.php +++ b/app/code/Magento/Catalog/Block/Product/View/Options.php @@ -206,19 +206,30 @@ class Options extends \Magento\Framework\View\Element\Template /* @var $option \Magento\Catalog\Model\Product\Option */ $priceValue = 0; if ($option->getGroupByType() == \Magento\Catalog\Model\Product\Option::OPTION_GROUP_SELECT) { - $_tmpPriceValues = []; + $tmpPriceValues = []; foreach ($option->getValues() as $value) { /* @var $value \Magento\Catalog\Model\Product\Option\Value */ $id = $value->getId(); - $_tmpPriceValues[$id] = $this->_getPriceConfiguration($value); + $tmpPriceValues[$id] = $this->_getPriceConfiguration($value); } - $priceValue = $_tmpPriceValues; + $priceValue = $tmpPriceValues; } else { $priceValue = $this->_getPriceConfiguration($option); } $config[$option->getId()] = $priceValue; } + $configObj = new \Magento\Framework\Object( + [ + 'config' => $config, + ] + ); + + //pass the return array encapsulated in an object for the other modules to be able to alter it eg: weee + $this->_eventManager->dispatch('catalog_product_option_price_configuration_after', ['configObj' => $configObj]); + + $config=$configObj->getConfig(); + return $this->_jsonEncoder->encode($config); } diff --git a/app/code/Magento/Catalog/Model/Observer.php b/app/code/Magento/Catalog/Model/Observer.php index 39e72883f68add9d3672497199eb7c744480a7db..417a4f61811c99663538fd72e3c790ddc0753f3c 100644 --- a/app/code/Magento/Catalog/Model/Observer.php +++ b/app/code/Magento/Catalog/Model/Observer.php @@ -34,7 +34,14 @@ class Observer * * @var \Magento\Catalog\Model\Layer */ - protected $_catalogLayer; + private $_catalogLayer = null; + + /** + * Catalog layer resolver + * + * @var \Magento\Catalog\Model\Layer\Resolver + */ + protected $layerResolver; /** * Store manager @@ -95,7 +102,7 @@ class Observer $this->_categoryResource = $categoryResource; $this->_catalogProduct = $catalogProduct; $this->_storeManager = $storeManager; - $this->_catalogLayer = $layerResolver->get(); + $this->layerResolver = $layerResolver; $this->_catalogCategory = $catalogCategory; $this->_catalogData = $catalogData; $this->categoryFlatConfig = $categoryFlatState; @@ -184,11 +191,12 @@ class Observer */ protected function hasActive($category) { - if (!$this->_catalogLayer) { + $catalogLayer = $this->getCatalogLayer(); + if (!$catalogLayer) { return false; } - $currentCategory = $this->_catalogLayer->getCurrentCategory(); + $currentCategory = $catalogLayer->getCurrentCategory(); if (!$currentCategory) { return false; } @@ -196,4 +204,16 @@ class Observer $categoryPathIds = explode(',', $currentCategory->getPathInStore()); return in_array($category->getId(), $categoryPathIds); } + + /** + * Get catalog layer + * @return \Magento\Catalog\Model\Layer + */ + private function getCatalogLayer() + { + if ($this->_catalogLayer === null) { + $this->_catalogLayer = $this->layerResolver->get(); + } + return $this->_catalogLayer; + } } diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index ebd9494fe1f842f7e42eba21cdb0c3da4cbd1325..d012f23de3df22b5e130abe2454fe2dc8f030c25 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -250,15 +250,25 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements protected $metadataService; /* - * @param \Magento\Catalog\Model\ProductLink\ProductLinkManagementInterface + * @param \Magento\Catalog\Model\ProductLink\CollectionProvider */ - protected $linkManagement; + protected $entityCollectionProvider; /* - * @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory + * @param \Magento\Catalog\Model\Product\LinkTypeProvider + */ + protected $linkProvider; + + /* + * @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory */ protected $productLinkFactory; + /* + * @param \Magento\Catalog\Api\Data\ProductLinkExtensionFactory + */ + protected $productLinkExtensionFactory; + /** * @var \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterfaceFactory */ @@ -318,8 +328,10 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements * @param Indexer\Product\Eav\Processor $productEavIndexerProcessor * @param CategoryRepositoryInterface $categoryRepository * @param Product\Image\CacheFactory $imageCacheFactory - * @param \Magento\Catalog\Model\ProductLink\Management $linkManagement - * @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory, + * @param \Magento\Catalog\Model\ProductLink\CollectionProvider $entityCollectionProvider + * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider + * @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory + * @param \Magento\Catalog\Api\Data\ProductLinkExtensionFactory $productLinkExtensionFactory * @param \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterfaceFactory $mediaGalleryEntryFactory * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper * @param array $data @@ -354,8 +366,10 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements \Magento\Catalog\Model\Indexer\Product\Eav\Processor $productEavIndexerProcessor, CategoryRepositoryInterface $categoryRepository, Product\Image\CacheFactory $imageCacheFactory, - \Magento\Catalog\Model\ProductLink\Management $linkManagement, + \Magento\Catalog\Model\ProductLink\CollectionProvider $entityCollectionProvider, + \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider, \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory, + \Magento\Catalog\Api\Data\ProductLinkExtensionFactory $productLinkExtensionFactory, \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterfaceFactory $mediaGalleryEntryFactory, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, array $data = [] @@ -380,8 +394,10 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements $this->_productEavIndexerProcessor = $productEavIndexerProcessor; $this->categoryRepository = $categoryRepository; $this->imageCacheFactory = $imageCacheFactory; - $this->linkManagement = $linkManagement; + $this->entityCollectionProvider = $entityCollectionProvider; + $this->linkTypeProvider = $linkTypeProvider; $this->productLinkFactory = $productLinkFactory; + $this->productLinkExtensionFactory = $productLinkExtensionFactory; $this->mediaGalleryEntryFactory = $mediaGalleryEntryFactory; $this->dataObjectHelper = $dataObjectHelper; parent::__construct( @@ -1352,23 +1368,34 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements public function getProductLinks() { if (empty($this->_links)) { - $productLinks = []; - - $productLinks['related'] = $this->getRelatedProducts(); - $productLinks['upsell'] = $this->getUpSellProducts(); - $productLinks['crosssell'] = $this->getCrossSellProducts(); - $output = []; - foreach ($productLinks as $type => $linkTypeArray) { - foreach ($linkTypeArray as $link) { + $linkTypes = $this->linkTypeProvider->getLinkTypes(); + foreach (array_keys($linkTypes) as $linkTypeName) { + $collection = $this->entityCollectionProvider->getCollection($this, $linkTypeName); + foreach ($collection as $item) { /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $productLink */ $productLink = $this->productLinkFactory->create(); $productLink->setProductSku($this->getSku()) - ->setLinkType($type) - ->setLinkedProductSku($link['sku']) - ->setLinkedProductType($link['type_id']) - ->setPosition($link['position']); - + ->setLinkType($linkTypeName) + ->setLinkedProductSku($item['sku']) + ->setLinkedProductType($item['type']) + ->setPosition($item['position']); + if (isset($item['custom_attributes'])) { + $productLinkExtension = $productLink->getExtensionAttributes(); + if ($productLinkExtension === null) { + $productLinkExtension = $this->productLinkExtensionFactory->create(); + } + foreach ($item['custom_attributes'] as $option) { + $name = $option['attribute_code']; + $value = $option['value']; + $setterName = 'set' . ucfirst($name); + // Check if setter exists + if (method_exists($productLinkExtension, $setterName)) { + call_user_func([$productLinkExtension, $setterName], $value); + } + } + $productLink->setExtensionAttributes($productLinkExtension); + } $output[] = $productLink; } } diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index 94612dbf200a5f95fc003342e0c114d273366be1..b40b91d5b08b8efa59ff0534e04600c1bfcc33d7 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -100,6 +100,13 @@ abstract class AbstractType */ protected $_fileStorageDb; + /** + * Cache key for Product Attributes + * + * @var string + */ + protected $_cacheProductSetAttributes = '_cache_instance_product_set_attributes'; + /** * Delete data specific for this product type * @@ -249,9 +256,13 @@ abstract class AbstractType */ public function getSetAttributes($product) { - return $product->getResource() - ->loadAllAttributes($product) - ->getSortedAttributes($product->getAttributeSetId()); + if (!$product->hasData($this->_cacheProductSetAttributes)) { + $setAttributes = $product->getResource() + ->loadAllAttributes($product) + ->getSortedAttributes($product->getAttributeSetId()); + $product->setData($this->_cacheProductSetAttributes, $setAttributes); + } + return $product->getData($this->_cacheProductSetAttributes); } /** diff --git a/app/code/Magento/Catalog/Model/ProductLink/Management.php b/app/code/Magento/Catalog/Model/ProductLink/Management.php index 558561d22de50af6f402f9201a6138aaba441496..e702a6cde0e41f1a8e3316d5a30be821c620fa0b 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Management.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Management.php @@ -7,7 +7,6 @@ namespace Magento\Catalog\Model\ProductLink; use Magento\Catalog\Api\Data; -use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks as LinksInitializer; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; @@ -18,26 +17,6 @@ class Management implements \Magento\Catalog\Api\ProductLinkManagementInterface */ protected $productRepository; - /** - * @var CollectionProvider - */ - protected $entityCollectionProvider; - - /** - * @var LinksInitializer - */ - protected $linkInitializer; - - /** - * @var \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory - */ - protected $productLinkFactory; - - /** - * @var \Magento\Catalog\Model\Resource\Product - */ - protected $productResource; - /** * @var \Magento\Catalog\Model\Product\LinkTypeProvider */ @@ -45,25 +24,13 @@ class Management implements \Magento\Catalog\Api\ProductLinkManagementInterface /** * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param CollectionProvider $collectionProvider - * @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory - * @param LinksInitializer $linkInitializer - * @param \Magento\Catalog\Model\Resource\Product $productResource * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider */ public function __construct( \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - CollectionProvider $collectionProvider, - \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory, - LinksInitializer $linkInitializer, - \Magento\Catalog\Model\Resource\Product $productResource, \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider ) { $this->productRepository = $productRepository; - $this->entityCollectionProvider = $collectionProvider; - $this->productLinkFactory = $productLinkFactory; - $this->productResource = $productResource; - $this->linkInitializer = $linkInitializer; $this->linkTypeProvider = $linkTypeProvider; } @@ -73,27 +40,22 @@ class Management implements \Magento\Catalog\Api\ProductLinkManagementInterface public function getLinkedItemsByType($sku, $type) { $output = []; - $product = $this->productRepository->get($sku); - try { - $collection = $this->entityCollectionProvider->getCollection($product, $type); - } catch (NoSuchEntityException $e) { + + $linkTypes = $this->linkTypeProvider->getLinkTypes(); + + if (!isset($linkTypes[$type])) { throw new NoSuchEntityException(__('Unknown link type: %1', (string)$type)); } - foreach ($collection as $item) { - /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $productLink */ - $productLink = $this->productLinkFactory->create(); - $productLink->setProductSku($product->getSku()) - ->setLinkType($type) - ->setLinkedProductSku($item['sku']) - ->setLinkedProductType($item['type']) - ->setPosition($item['position']); - if (isset($item['custom_attributes'])) { - foreach ($item['custom_attributes'] as $option) { - $productLink->getExtensionAttributes()->setQty($option['value']); - } + $product = $this->productRepository->get($sku); + $links = $product->getProductLinks(); + + // Only return the links of type specified + foreach ($links as $link) { + if ($link->getLinkType() == $type) { + $output[] = $link; } - $output[] = $productLink; } + return $output; } @@ -111,32 +73,27 @@ class Management implements \Magento\Catalog\Api\ProductLinkManagementInterface } $product = $this->productRepository->get($sku); - $assignedSkuList = []; - /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */ - foreach ($items as $link) { - $assignedSkuList[] = $link->getLinkedProductSku(); - } - $linkedProductIds = $this->productResource->getProductsIdsBySkus($assignedSkuList); - $links = []; - /** @var \Magento\Catalog\Api\Data\ProductLinkInterface[] $items*/ - foreach ($items as $link) { - $data = $link->__toArray(); - $linkedSku = $link->getLinkedProductSku(); - if (!isset($linkedProductIds[$linkedSku])) { - throw new NoSuchEntityException( - __('Product with SKU "%1" does not exist', $linkedSku) - ); + // Replace only links of the specified type + $existingLinks = $product->getProductLinks(); + $newLinks = []; + if (!empty($existingLinks)) { + foreach ($existingLinks as $link) { + if ($link->getLinkType() != $type) { + $newLinks[] = $link; + } } - $data['product_id'] = $linkedProductIds[$linkedSku]; - $links[$linkedProductIds[$linkedSku]] = $data; + $newLinks = array_merge($newLinks, $items); + } else { + $newLinks = $items; } - $this->linkInitializer->initializeLinks($product, [$type => $links]); + $product->setProductLinks($newLinks); try { - $product->save(); + $this->productRepository->save($product); } catch (\Exception $exception) { throw new CouldNotSaveException(__('Invalid data provided for linked products')); } + return true; } } diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 40ecc5d2cb3419101374a9d563b52ada19cd9967..8f2e7664c4e3df2c3ebf963cd4122e22a0e730cb 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -75,6 +75,16 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa */ protected $linkInitializer; + /* + * @param \Magento\Catalog\Model\Product\LinkTypeProvider + */ + protected $linkTypeProvider; + + /* + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + */ + protected $storeManager; + /** * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface */ @@ -129,6 +139,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository * @param Resource\Product $resourceModel * @param \Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks $linkInitializer + * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider + * @param \Magento\Store\Model\StoreManagerInterface $storeManager, * @param \Magento\Framework\Api\FilterBuilder $filterBuilder * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $metadataServiceInterface * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter @@ -149,6 +161,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository, \Magento\Catalog\Model\Resource\Product $resourceModel, \Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks $linkInitializer, + \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider, + \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Api\FilterBuilder $filterBuilder, \Magento\Catalog\Api\ProductAttributeRepositoryInterface $metadataServiceInterface, \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter, @@ -166,6 +180,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->resourceModel = $resourceModel; $this->linkInitializer = $linkInitializer; + $this->linkTypeProvider = $linkTypeProvider; + $this->storeManager = $storeManager; $this->attributeRepository = $attributeRepository; $this->filterBuilder = $filterBuilder; $this->metadataService = $metadataServiceInterface; @@ -260,6 +276,9 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa { if ($createNew) { $product = $this->productFactory->create(); + if ($this->storeManager->hasSingleStore()) { + $product->setWebsiteIds([$this->storeManager->getStore(true)->getWebsite()->getId()]); + } } else { unset($this->instances[$productData['sku']]); $product = $this->get($productData['sku']); @@ -353,11 +372,12 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa } // Clear all existing product links and then set the ones we want - $this->linkInitializer->initializeLinks($product, ['related' => []]); - $this->linkInitializer->initializeLinks($product, ['upsell' => []]); - $this->linkInitializer->initializeLinks($product, ['crosssell' => []]); + $linkTypes = $this->linkTypeProvider->getLinkTypes(); + foreach (array_keys($linkTypes) as $typeName) { + $this->linkInitializer->initializeLinks($product, [$typeName => []]); + } - // Gather each linktype info + // Set each linktype info if (!empty($newLinks)) { $productLinks = []; foreach ($newLinks as $link) { diff --git a/app/code/Magento/Catalog/Model/Resource/Category.php b/app/code/Magento/Catalog/Model/Resource/Category.php index f99d1b9ee9d2c15cdca6c883cc7ded953973afc7..27d7f8b801df56c735259f20150e53aa1a5d7af4 100644 --- a/app/code/Magento/Catalog/Model/Resource/Category.php +++ b/app/code/Magento/Catalog/Model/Resource/Category.php @@ -92,13 +92,36 @@ class Category extends AbstractResource $this->_categoryTreeFactory = $categoryTreeFactory; $this->_categoryCollectionFactory = $categoryCollectionFactory; $this->_eventManager = $eventManager; - $this->setType( - \Magento\Catalog\Model\Category::ENTITY - )->setConnection( - $this->_resource->getConnection('catalog_read'), - $this->_resource->getConnection('catalog_write') - ); - $this->_categoryProductTable = $this->getTable('catalog_category_product'); + + $this->_read = 'catalog_read'; + $this->_write = 'catalog_write'; + } + + /** + * Entity type getter and lazy loader + * + * @return \Magento\Eav\Model\Entity\Type + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getEntityType() + { + if (empty($this->_type)) { + $this->setType(\Magento\Catalog\Model\Category::ENTITY); + } + return parent::getEntityType(); + } + + /** + * Category product table name getter + * + * @return string + */ + public function getCategoryProductTable() + { + if (!$this->_categoryProductTable) { + $this->_categoryProductTable = $this->getTable('catalog_category_product'); + } + return $this->_categoryProductTable; } /** @@ -359,7 +382,7 @@ class Category extends AbstractResource */ if (!empty($delete)) { $cond = ['product_id IN(?)' => array_keys($delete), 'category_id=?' => $id]; - $adapter->delete($this->_categoryProductTable, $cond); + $adapter->delete($this->getCategoryProductTable(), $cond); } /** @@ -374,7 +397,7 @@ class Category extends AbstractResource 'position' => (int)$position, ]; } - $adapter->insertMultiple($this->_categoryProductTable, $data); + $adapter->insertMultiple($this->getCategoryProductTable(), $data); } /** @@ -384,7 +407,7 @@ class Category extends AbstractResource foreach ($update as $productId => $position) { $where = ['category_id = ?' => (int)$id, 'product_id = ?' => (int)$productId]; $bind = ['position' => (int)$position]; - $adapter->update($this->_categoryProductTable, $bind, $where); + $adapter->update($this->getCategoryProductTable(), $bind, $where); } } @@ -417,7 +440,7 @@ class Category extends AbstractResource public function getProductsPosition($category) { $select = $this->_getWriteAdapter()->select()->from( - $this->_categoryProductTable, + $this->getCategoryProductTable(), ['product_id', 'position'] )->where( 'category_id = :category_id' diff --git a/app/code/Magento/Catalog/Model/Resource/Category/Collection.php b/app/code/Magento/Catalog/Model/Resource/Category/Collection.php index 2abc203eccbcada147503ce7f5be4400deb898e8..f21ce9f363b51f01a7555d79e3ba39aa89598b53 100644 --- a/app/code/Magento/Catalog/Model/Resource/Category/Collection.php +++ b/app/code/Magento/Catalog/Model/Resource/Category/Collection.php @@ -33,7 +33,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl * * @var string */ - protected $_productTable; + private $_productTable; /** * Store id, that we should count products on @@ -47,7 +47,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl * * @var string */ - protected $_productWebsiteTable; + private $_productWebsiteTable; /** * Load with product count flag @@ -64,9 +64,6 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl protected function _construct() { $this->_init('Magento\Catalog\Model\Category', 'Magento\Catalog\Model\Resource\Category'); - - $this->_productWebsiteTable = $this->getTable('catalog_product_website'); - $this->_productTable = $this->getTable('catalog_category_product'); } /** @@ -224,7 +221,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl if (!empty($regularIds)) { $select = $this->_conn->select(); $select->from( - ['main_table' => $this->_productTable], + ['main_table' => $this->getProductTable()], ['category_id', new \Zend_Db_Expr('COUNT(main_table.product_id)')] )->where( $this->_conn->quoteInto('main_table.category_id IN(?)', $regularIds) @@ -233,7 +230,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl ); if ($websiteId) { $select->join( - ['w' => $this->_productWebsiteTable], + ['w' => $this->getProductWebsiteTable()], 'main_table.product_id = w.product_id', [] )->where( @@ -259,7 +256,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl $bind = ['entity_id' => $item->getId(), 'c_path' => $item->getPath() . '/%']; $select = $this->_conn->select(); $select->from( - ['main_table' => $this->_productTable], + ['main_table' => $this->getProductTable()], new \Zend_Db_Expr('COUNT(DISTINCT main_table.product_id)') )->joinInner( ['e' => $this->getTable('catalog_category_entity')], @@ -272,7 +269,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl ); if ($websiteId) { $select->join( - ['w' => $this->_productWebsiteTable], + ['w' => $this->getProductWebsiteTable()], 'main_table.product_id = w.product_id', [] )->where( @@ -416,4 +413,30 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl $this->setOrder($field, self::SORT_ORDER_ASC); return $this; } + + /** + * Getter for _productWebsiteTable + * + * @return string + */ + public function getProductWebsiteTable() + { + if (empty($this->_productWebsiteTable)) { + $this->_productWebsiteTable = $this->getTable('catalog_product_website'); + } + return $this->_productWebsiteTable; + } + + /** + * Getter for _productTable + * + * @return string + */ + public function getProductTable() + { + if (empty($this->_productTable)) { + $this->_productTable = $this->getTable('catalog_category_product'); + } + return $this->_productTable; + } } diff --git a/app/code/Magento/Catalog/Model/Resource/Product.php b/app/code/Magento/Catalog/Model/Resource/Product.php index 336d8f796577ecabad0284932cc213cabcfb5f28..6f02829d2bc2a7dff4e95b39b7cd20181d5d1903 100644 --- a/app/code/Magento/Catalog/Model/Resource/Product.php +++ b/app/code/Magento/Catalog/Model/Resource/Product.php @@ -91,9 +91,48 @@ class Product extends AbstractResource $modelFactory, $data ); - $this->setType(\Magento\Catalog\Model\Product::ENTITY)->setConnection('catalog_read', 'catalog_write'); - $this->_productWebsiteTable = $this->getTable('catalog_product_website'); - $this->_productCategoryTable = $this->getTable('catalog_category_product'); + $this->_read = 'catalog_read'; + $this->_write = 'catalog_write'; + } + + /** + * Entity type getter and lazy loader + * + * @return \Magento\Eav\Model\Entity\Type + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getEntityType() + { + if (empty($this->_type)) { + $this->setType(\Magento\Catalog\Model\Product::ENTITY); + } + return parent::getEntityType(); + } + + /** + * Product Website table name getter + * + * @return string + */ + public function getProductWebsiteTable() + { + if (!$this->_productWebsiteTable) { + $this->_productWebsiteTable = $this->getTable('catalog_product_website'); + } + return $this->_productWebsiteTable; + } + + /** + * Product Category table name getter + * + * @return string + */ + public function getProductCategoryTable() + { + if (!$this->_productCategoryTable) { + $this->_productCategoryTable = $this->getTable('catalog_category_product'); + } + return $this->_productCategoryTable; } /** @@ -123,7 +162,7 @@ class Product extends AbstractResource } $select = $adapter->select()->from( - $this->_productWebsiteTable, + $this->getProductWebsiteTable(), 'website_id' )->where( 'product_id = ?', @@ -142,7 +181,7 @@ class Product extends AbstractResource public function getWebsiteIdsByProductIds($productIds) { $select = $this->_getWriteAdapter()->select()->from( - $this->_productWebsiteTable, + $this->getProductWebsiteTable(), ['product_id', 'website_id'] )->where( 'product_id IN (?)', @@ -171,7 +210,7 @@ class Product extends AbstractResource $adapter = $this->_getReadAdapter(); $select = $adapter->select()->from( - $this->_productCategoryTable, + $this->getProductCategoryTable(), 'category_id' )->where( 'product_id = ?', @@ -274,14 +313,14 @@ class Product extends AbstractResource foreach ($insert as $websiteId) { $data[] = ['product_id' => (int)$product->getId(), 'website_id' => (int)$websiteId]; } - $adapter->insertMultiple($this->_productWebsiteTable, $data); + $adapter->insertMultiple($this->getProductWebsiteTable(), $data); } if (!empty($delete)) { foreach ($delete as $websiteId) { $condition = ['product_id = ?' => (int)$product->getId(), 'website_id = ?' => (int)$websiteId]; - $adapter->delete($this->_productWebsiteTable, $condition); + $adapter->delete($this->getProductWebsiteTable(), $condition); } } @@ -329,7 +368,7 @@ class Product extends AbstractResource ]; } if ($data) { - $write->insertMultiple($this->_productCategoryTable, $data); + $write->insertMultiple($this->getProductCategoryTable(), $data); } } @@ -337,7 +376,7 @@ class Product extends AbstractResource foreach ($delete as $categoryId) { $where = ['product_id = ?' => (int)$object->getId(), 'category_id = ?' => (int)$categoryId]; - $write->delete($this->_productCategoryTable, $where); + $write->delete($this->getProductCategoryTable(), $where); } } diff --git a/app/code/Magento/Catalog/Model/Session.php b/app/code/Magento/Catalog/Model/Session.php index b61175b11e7da3ff879834074f303590b664b72b..d7a3748c2810bd82a6b856e4d7dfe814cd0401ab 100644 --- a/app/code/Magento/Catalog/Model/Session.php +++ b/app/code/Magento/Catalog/Model/Session.php @@ -8,6 +8,6 @@ namespace Magento\Catalog\Model; /** * Catalog session model */ -class Session extends \Magento\Framework\Session\Generic +class Session extends \Magento\Framework\Session\SessionManager { } diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/ToolbarTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/ToolbarTest.php index df66448c160372d82452ebe45b9ac68b7bb08749..d4501bd7d04393062a693c3491482132a7565d7d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/ToolbarTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/ToolbarTest.php @@ -106,9 +106,6 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase '', false ); - $this->catalogConfig->expects($this->any()) - ->method('getAttributeUsedForSortByArray') - ->will($this->returnValue(['name' => [], 'price' => []])); $context = $this->getMock( 'Magento\Framework\View\Element\Template\Context', @@ -133,9 +130,6 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase '', false ); - $this->productListHelper->expects($this->any()) - ->method('getAvailableViewMode') - ->will($this->returnValue(['list' => 'List'])); $this->urlEncoder = $this->getMock('Magento\Framework\Url\EncoderInterface', ['encode'], [], '', false); $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -187,6 +181,9 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase $this->model->expects($this->once()) ->method('getOrder') ->will($this->returnValue($order)); + $this->catalogConfig->expects($this->once()) + ->method('getAttributeUsedForSortByArray') + ->will($this->returnValue(['name' => [], 'price' => []])); $this->assertEquals($order, $this->block->getCurrentOrder()); } @@ -206,6 +203,9 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase { $mode = 'list'; + $this->productListHelper->expects($this->once()) + ->method('getAvailableViewMode') + ->will($this->returnValue(['list' => 'List'])); $this->model->expects($this->once()) ->method('getMode') ->will($this->returnValue($mode)); @@ -213,6 +213,40 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase $this->assertEquals($mode, $this->block->getCurrentMode()); } + public function testGetModes() + { + $mode = ['list' => 'List']; + $this->productListHelper->expects($this->once()) + ->method('getAvailableViewMode') + ->will($this->returnValue($mode)); + + $this->assertEquals($mode, $this->block->getModes()); + $this->assertEquals($mode, $this->block->getModes()); + } + + /** + * @param string[] $mode + * @param string[] $expected + * @dataProvider setModesDataProvider + */ + public function testSetModes($mode, $expected) + { + $this->productListHelper->expects($this->once()) + ->method('getAvailableViewMode') + ->will($this->returnValue($mode)); + + $block = $this->block->setModes(['mode' => 'mode']); + $this->assertEquals($expected, $block->getModes()); + } + + public function setModesDataProvider() + { + return [ + [['list' => 'List'], ['list' => 'List']], + [null, ['mode' => 'mode']], + ]; + } + public function testGetLimit() { $mode = 'list'; @@ -232,6 +266,9 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase ->method('getDefaultLimitPerPageValue') ->with($this->equalTo('list')) ->will($this->returnValue(10)); + $this->productListHelper->expects($this->any()) + ->method('getAvailableViewMode') + ->will($this->returnValue(['list' => 'List'])); $this->assertEquals($limit, $this->block->getLimit()); } @@ -280,4 +317,48 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase $this->assertTrue($this->block->getPagerHtml()); } + + public function testSetDefaultOrder() + { + $this->catalogConfig->expects($this->atLeastOnce()) + ->method('getAttributeUsedForSortByArray') + ->will($this->returnValue(['name' => [], 'price' => []])); + + $this->block->setDefaultOrder('field'); + } + + public function testGetAvailableOrders() + { + $data = ['name' => [], 'price' => []]; + $this->catalogConfig->expects($this->once()) + ->method('getAttributeUsedForSortByArray') + ->will($this->returnValue($data)); + + $this->assertEquals($data, $this->block->getAvailableOrders()); + $this->assertEquals($data, $this->block->getAvailableOrders()); + } + + public function testAddOrderToAvailableOrders() + { + $data = ['name' => [], 'price' => []]; + $this->catalogConfig->expects($this->once()) + ->method('getAttributeUsedForSortByArray') + ->will($this->returnValue($data)); + $expected = $data; + $expected['order'] = 'value'; + $toolbar = $this->block->addOrderToAvailableOrders('order', 'value'); + $this->assertEquals($expected, $toolbar->getAvailableOrders()); + } + + public function testRemoveOrderFromAvailableOrders() + { + $data = ['name' => [], 'price' => []]; + $this->catalogConfig->expects($this->once()) + ->method('getAttributeUsedForSortByArray') + ->will($this->returnValue($data)); + $toolbar = $this->block->removeOrderFromAvailableOrders('order', 'value'); + $this->assertEquals($data, $toolbar->getAvailableOrders()); + $toolbar2 = $this->block->removeOrderFromAvailableOrders('name'); + $this->assertEquals(['price' => []], $toolbar2->getAvailableOrders()); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Type/AbstractTypeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Type/AbstractTypeTest.php index 75149c26c8d001cf51956b2ca893ecb326f801d4..0ce39e12fbdc93ee8f2e1d38eff837c5a9b25514 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Type/AbstractTypeTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Type/AbstractTypeTest.php @@ -119,11 +119,12 @@ class AbstractTypeTest extends \PHPUnit_Framework_TestCase public function testGetSetAttributes() { - $this->productResource->expects($this->any())->method('loadAllAttributes')->will( + $this->productResource->expects($this->once())->method('loadAllAttributes')->will( $this->returnValue($this->productResource) ); - $this->productResource->expects($this->any())->method('getSortedAttributes')->will($this->returnValue(5)); - $this->model->getSetAttributes($this->product); + $this->productResource->expects($this->once())->method('getSortedAttributes')->will($this->returnValue(5)); + $this->assertEquals(5, $this->model->getSetAttributes($this->product)); + //Call the method for a second time, the cached copy should be used $this->assertEquals(5, $this->model->getSetAttributes($this->product)); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php index ed28dc6fda78135af0e50f4e57d7db7c656dac67..92c2026f8961c258516299ba309da2cb811c145c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php @@ -26,58 +26,21 @@ class ManagementTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $collectionProviderMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $linkInitializerMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $productLinkFactoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $productResourceMock; + protected $productMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $productMock; + protected $linkTypeProviderMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\ObjectManager */ - protected $linkTypeProviderMock; + protected $objectManager; protected function setUp() { $this->productRepositoryMock = $this->getMock('\Magento\Catalog\Model\ProductRepository', [], [], '', false); - $this->productResourceMock = $this->getMock('\Magento\Catalog\Model\Resource\Product', [], [], '', false); - $this->collectionProviderMock = $this->getMock( - '\Magento\Catalog\Model\ProductLink\CollectionProvider', - [], - [], - '', - false - ); - $this->linkInitializerMock = $this->getMock( - '\Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks', - [], - [], - '', - false - ); - $this->productLinkFactoryMock = $this->getMock( - '\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory', - ['create'], - [], - '', - false - ); $this->productMock = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false); $this->linkTypeProviderMock = $this->getMock( @@ -88,15 +51,11 @@ class ManagementTest extends \PHPUnit_Framework_TestCase false ); - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->model = $objectManager->getObject( + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $this->objectManager->getObject( 'Magento\Catalog\Model\ProductLink\Management', [ 'productRepository' => $this->productRepositoryMock, - 'collectionProvider' => $this->collectionProviderMock, - 'productLinkFactory' => $this->productLinkFactoryMock, - 'linkInitializer' => $this->linkInitializerMock, - 'productResource' => $this->productResourceMock, 'linkTypeProvider' => $this->linkTypeProviderMock ] ); @@ -104,163 +63,135 @@ class ManagementTest extends \PHPUnit_Framework_TestCase public function testGetLinkedItemsByType() { - $productSku = 'product'; - $linkType = 'link'; + $productSku = 'Simple Product 1'; + $linkType = 'related'; $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) ->willReturn($this->productMock); - $item = [ - 'sku' => 'product1', - 'type' => 'type1', - 'position' => 'pos1', - ]; - $itemCollection = [$item]; - $this->collectionProviderMock->expects($this->once()) - ->method('getCollection') - ->with($this->productMock, $linkType) - ->willReturn($itemCollection); - $this->productMock->expects($this->once())->method('getSku')->willReturn($productSku); - $productLinkMock = $this->getMock('\Magento\Catalog\Api\Data\ProductLinkInterface'); - $productLinkMock->expects($this->once()) - ->method('setProductSku') - ->with($productSku) - ->willReturnSelf(); - $productLinkMock->expects($this->once()) - ->method('setLinkType') - ->with($linkType) - ->willReturnSelf(); - $productLinkMock->expects($this->once()) - ->method('setLinkedProductSku') - ->with($item['sku']) - ->willReturnSelf(); - $productLinkMock->expects($this->once()) - ->method('setLinkedProductType') - ->with($item['type']) - ->willReturnSelf(); - $productLinkMock->expects($this->once()) - ->method('setPosition') - ->with($item['position']) - ->willReturnSelf(); - $this->productLinkFactoryMock->expects($this->once())->method('create')->willReturn($productLinkMock); - $this->assertEquals([$productLinkMock], $this->model->getLinkedItemsByType($productSku, $linkType)); + + $inputRelatedLink = $this->objectManager->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku($productSku); + $inputRelatedLink->setLinkType($linkType); + $inputRelatedLink->setData("sku", "Simple Product 2"); + $inputRelatedLink->setData("type_id", "simple"); + $inputRelatedLink->setPosition(0); + $links = [$inputRelatedLink]; + + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $this->productMock->expects($this->once())->method('getProductLinks')->willReturn($links); + $this->assertEquals($links, $this->model->getLinkedItemsByType($productSku, $linkType)); } /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Unknown link type: wrong_type + * @expectedExceptionMessage Unknown link type: bad type */ public function testGetLinkedItemsByTypeWithWrongType() { - $productSku = 'product'; - $linkType = 'wrong_type'; - - $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) + $productSku = 'Simple Product 1'; + $linkType = 'bad type'; + $this->productRepositoryMock->expects($this->never())->method('get')->with($productSku) ->willReturn($this->productMock); - $this->collectionProviderMock->expects($this->once()) - ->method('getCollection') - ->with($this->productMock, $linkType) - ->willThrowException(new NoSuchEntityException(__('Collection provider is not registered'))); + $inputRelatedLink = $this->objectManager->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku($productSku); + $inputRelatedLink->setLinkType($linkType); + $inputRelatedLink->setData("sku", "Simple Product 2"); + $inputRelatedLink->setData("type_id", "simple"); + $inputRelatedLink->setPosition(0); + $links = [$inputRelatedLink]; + + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $this->productMock->expects($this->never())->method('getProductLinks')->willReturn($links); $this->model->getLinkedItemsByType($productSku, $linkType); } public function testSetProductLinks() { - $type = 'type'; - $linkedProductsMock = []; - $linksData = []; - - $this->linkTypeProviderMock->expects($this->once())->method('getLinkTypes')->willReturn([$type => 'link']); - for ($i = 0; $i < 2; $i++) { - $linkMock = $this->getMockForAbstractClass( - '\Magento\Catalog\Api\Data\ProductLinkInterface', - [], - '', - false, - false, - true, - ['getLinkedProductSku', '__toArray'] - ); - $linkMock->expects($this->exactly(2)) - ->method('getLinkedProductSku') - ->willReturn('linkedProduct' . $i . 'Sku'); - $linkMock->expects($this->once())->method('__toArray'); - $linkedProductsMock[$i] = $linkMock; - $linksData['productSku']['link'][] = $linkMock; - } - $linkedSkuList = ['linkedProduct0Sku', 'linkedProduct1Sku']; - $linkedProductIds = ['linkedProduct0Sku' => 1, 'linkedProduct1Sku' => 2]; - - $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus')->with($linkedSkuList) - ->willReturn($linkedProductIds); - $this->productRepositoryMock->expects($this->once())->method('get')->willReturn($this->productMock); - $this->linkInitializerMock->expects($this->once())->method('initializeLinks') - ->with($this->productMock, [$type => [ - 1 => ['product_id' => 1], - 2 => ['product_id' => 2], - ]]); - $this->productMock->expects($this->once())->method('save'); - $this->assertTrue($this->model->setProductLinks('', $type, $linkedProductsMock)); + $productSku = 'Simple Product 1'; + $linkType = 'related'; + $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) + ->willReturn($this->productMock); + + $inputRelatedLink = $this->objectManager->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku($productSku); + $inputRelatedLink->setLinkType($linkType); + $inputRelatedLink->setData("sku", "Simple Product 1"); + $inputRelatedLink->setData("type_id", "related"); + $inputRelatedLink->setPosition(0); + $links = [$inputRelatedLink]; + + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $this->productMock->expects($this->once())->method('getProductLinks')->willReturn([]); + $this->productMock->expects($this->once())->method('setProductLinks')->with($links); + $this->assertTrue($this->model->setProductLinks($productSku, $linkType, $links)); } /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Provided link type "type2" does not exist + * @expectedExceptionMessage Provided link type "bad type" does not exist */ public function testSetProductLinksThrowExceptionIfProductLinkTypeDoesNotExist() { - $type = 'type'; - $linkedProductsMock = []; + $productSku = 'Simple Product 1'; + $linkType = 'bad type'; + $this->productRepositoryMock->expects($this->never())->method('get')->with($productSku) + ->willReturn($this->productMock); + + $inputRelatedLink = $this->objectManager->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku($productSku); + $inputRelatedLink->setLinkType($linkType); + $inputRelatedLink->setData("sku", "Simple Product 2"); + $inputRelatedLink->setData("type_id", "simple"); + $inputRelatedLink->setPosition(0); + $links = [$inputRelatedLink]; - $this->linkTypeProviderMock->expects($this->once())->method('getLinkTypes')->willReturn([$type => 'link']); - $this->assertTrue($this->model->setProductLinks('', 'type2', $linkedProductsMock)); + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $this->assertTrue($this->model->setProductLinks('', $linkType, $links)); } /** - * @dataProvider setProductLinksNoProductExceptionDataProvider + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested product doesn't exist */ - public function testSetProductLinksNoProductException($exceptionName, $exceptionMessage, $linkedProductIds) + public function testSetProductLinksNoProductException() { - $this->setExpectedException($exceptionName, $exceptionMessage); - $linkedProductsMock = []; - $type = 'type'; - $this->linkTypeProviderMock->expects($this->once())->method('getLinkTypes')->willReturn([$type => 'link']); - for ($i = 0; $i < 2; $i++) { - $productLinkMock = $this->getMock( - '\Magento\Catalog\Api\Data\ProductLinkInterface', - [ - 'getLinkedProductSku', 'getProductSku', 'getLinkType', - '__toArray', 'getLinkedProductType', 'getPosition', 'getCustomAttribute', 'getCustomAttributes', - 'setCustomAttribute', 'setCustomAttributes', 'getMetadataServiceInterface', - 'getExtensionAttributes', 'setExtensionAttributes', - 'setLinkedProductSku', 'setProductSku', 'setLinkType', 'setLinkedProductType', 'setPosition' - ] - ); - $productLinkMock->expects($this->any()) - ->method('getLinkedProductSku') - ->willReturn('linkedProduct' . $i . 'Sku'); - $productLinkMock->expects($this->any())->method('getProductSku')->willReturn('productSku'); - $productLinkMock->expects($this->any())->method('getLinkType')->willReturn('link'); - $linkedProductsMock[$i] = $productLinkMock; - } - $linkedSkuList = ['linkedProduct0Sku', 'linkedProduct1Sku']; - $this->productResourceMock->expects($this->any())->method('getProductsIdsBySkus')->with($linkedSkuList) - ->willReturn($linkedProductIds); - $this->model->setProductLinks('', $type, $linkedProductsMock); - } - - public function setProductLinksNoProductExceptionDataProvider() - { - return [ - [ - '\Magento\Framework\Exception\NoSuchEntityException', - 'Product with SKU "linkedProduct0Sku" does not exist', - ['linkedProduct1Sku' => 2], - ], [ - '\Magento\Framework\Exception\NoSuchEntityException', - 'Product with SKU "linkedProduct1Sku" does not exist', - ['linkedProduct0Sku' => 1] - ] - ]; + $productSku = 'Simple Product 1'; + $linkType = 'related'; + + $inputRelatedLink = $this->objectManager->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku($productSku); + $inputRelatedLink->setLinkType($linkType); + $inputRelatedLink->setData("sku", "Simple Product 2"); + $inputRelatedLink->setData("type_id", "simple"); + $inputRelatedLink->setPosition(0); + $links = [$inputRelatedLink]; + + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->will($this->throwException( + new \Magento\Framework\Exception\NoSuchEntityException(__('Requested product doesn\'t exist')))); + $this->model->setProductLinks($productSku, $linkType, $links); } /** @@ -269,39 +200,27 @@ class ManagementTest extends \PHPUnit_Framework_TestCase */ public function testSetProductLinksInvalidDataException() { - $type = 'type'; - $linkedProductsMock = []; - $linksData = []; - $this->linkTypeProviderMock->expects($this->once())->method('getLinkTypes')->willReturn([$type => 'link']); - for ($i = 0; $i < 2; $i++) { - $linkMock = $this->getMockForAbstractClass( - '\Magento\Catalog\Api\Data\ProductLinkInterface', - [], - '', - false, - false, - true, - ['getLinkedProductSku', '__toArray'] - ); - $linkMock->expects($this->exactly(2)) - ->method('getLinkedProductSku') - ->willReturn('linkedProduct' . $i . 'Sku'); - $linkMock->expects($this->once())->method('__toArray'); - $linkedProductsMock[$i] = $linkMock; - $linksData['productSku']['link'][] = $linkMock; - } - $linkedSkuList = ['linkedProduct0Sku', 'linkedProduct1Sku']; - $linkedProductIds = ['linkedProduct0Sku' => 1, 'linkedProduct1Sku' => 2]; - - $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus')->with($linkedSkuList) - ->willReturn($linkedProductIds); - $this->productRepositoryMock->expects($this->once())->method('get')->willReturn($this->productMock); - $this->linkInitializerMock->expects($this->once())->method('initializeLinks') - ->with($this->productMock, [$type => [ - 1 => ['product_id' => 1], - 2 => ['product_id' => 2], - ]]); - $this->productMock->expects($this->once())->method('save')->willThrowException(new \Exception()); - $this->model->setProductLinks('', $type, $linkedProductsMock); + $productSku = 'Simple Product 1'; + $linkType = 'related'; + $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) + ->willReturn($this->productMock); + + $inputRelatedLink = $this->objectManager->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku($productSku); + $inputRelatedLink->setLinkType($linkType); + $inputRelatedLink->setData("sku", "bad sku"); + $inputRelatedLink->setData("type_id", "bad type"); + $inputRelatedLink->setPosition(0); + $links = [$inputRelatedLink]; + + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $this->productMock->expects($this->once())->method('getProductLinks')->willReturn([]); + + $this->productRepositoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + $this->model->setProductLinks($productSku, $linkType, $links); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index a8ba184519d797718c4613f9e5f4c4c8690764bf..35b260532553ee98240c049b12e1116449fbc9d9 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -111,11 +111,19 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $contentValidatorMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $linkTypeProviderMock; + /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ protected $objectManager; + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ protected function setUp() { $this->productFactoryMock = $this->getMock('Magento\Catalog\Model\ProductFactory', ['create'], [], '', false); @@ -194,6 +202,8 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); $optionConverter = $this->objectManager->getObject('Magento\Catalog\Model\Product\Option\Converter'); + $this->linkTypeProviderMock = $this->getMock('Magento\Catalog\Model\Product\LinkTypeProvider', + ['getLinkTypes'], [], '', false); $this->model = $this->objectManager->getObject( 'Magento\Catalog\Model\ProductRepository', [ @@ -212,6 +222,7 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase 'fileSystem' => $this->fileSystemMock, 'contentFactory' => $this->contentFactoryMock, 'mimeTypeExtensionMap' => $this->mimeTypeExtensionMapMock, + 'linkTypeProvider' => $this->linkTypeProviderMock ] ); } @@ -847,6 +858,11 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase $this->initializedProductMock->setData("product_links", $existingLinks); if (!empty($newLinks)) { + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + $this->initializedProductMock->setData("ignore_links_flag", false); $this->resourceModelMock ->expects($this->any())->method('getProductsIdsBySkus') @@ -859,6 +875,10 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase $inputLink->setLinkedProductType($newLinks['linked_product_type']); $inputLink->setPosition($newLinks['position']); + if (isset($newLinks['qty'])) { + $inputLink->setQty($newLinks['qty']); + } + $this->productData['product_links'] = [$inputLink]; $this->initializedProductMock->expects($this->any()) @@ -898,6 +918,9 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase $outputLink->setLinkedProductSku($link['linked_product_sku']); $outputLink->setLinkedProductType($link['linked_product_type']); $outputLink->setPosition($link['position']); + if (isset($link['qty'])) { + $outputLink->setQty($link['qty']); + } $outputLinks[] = $outputLink; } @@ -913,11 +936,11 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase // Scenario 1 // No existing, new links $data['scenario_1'] = [ - 'newLinks' => ["product_sku" => "Simple Product 1", "link_type" => "related", "linked_product_sku" => - "Simple Product 2", "linked_product_type" => "simple", "position" => 0], + 'newLinks' => ["product_sku" => "Simple Product 1", "link_type" => "associated", "linked_product_sku" => + "Simple Product 2", "linked_product_type" => "simple", "position" => 0, "qty" => 1], 'existingLinks' => [], - 'expectedData' => [["product_sku" => "Simple Product 1", "link_type" => "related", "linked_product_sku" => - "Simple Product 2", "linked_product_type" => "simple", "position" => 0]] + 'expectedData' => [["product_sku" => "Simple Product 1", "link_type" => "associated", "linked_product_sku" => + "Simple Product 2", "linked_product_type" => "simple", "position" => 0, "qty" => 1]] ]; // Scenario 2 diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php index 4dcd067721f5bc239c97b1aa0141e694fb8a7f07..4cc87c7011c705075f1cb321657748006efc6aa6 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php @@ -146,6 +146,16 @@ class ProductTest extends \PHPUnit_Framework_TestCase */ protected $attributeValueFactory; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $linkTypeProviderMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $entityCollectionProviderMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -283,6 +293,11 @@ class ProductTest extends \PHPUnit_Framework_TestCase $this->metadataServiceMock = $this->getMock('\Magento\Catalog\Api\ProductAttributeRepositoryInterface'); $this->attributeValueFactory = $this->getMockBuilder('Magento\Framework\Api\AttributeValueFactory') ->disableOriginalConstructor()->getMock(); + $this->linkTypeProviderMock = $this->getMock('Magento\Catalog\Model\Product\LinkTypeProvider', + ['getLinkTypes'], [], '', false); + $this->entityCollectionProviderMock = $this->getMock('Magento\Catalog\Model\ProductLink\CollectionProvider', + ['getCollection'], [], '', false); + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->model = $this->objectManagerHelper->getObject( 'Magento\Catalog\Model\Product', @@ -306,6 +321,8 @@ class ProductTest extends \PHPUnit_Framework_TestCase 'mediaGalleryEntryFactory' => $this->mediaGalleryEntryFactoryMock, 'metadataService' => $this->metadataServiceMock, 'customAttributeFactory' => $this->attributeValueFactory, + 'entityCollectionProvider' => $this->entityCollectionProviderMock, + 'linkTypeProvider' => $this->linkTypeProviderMock, 'data' => ['id' => 1] ] ); @@ -737,37 +754,43 @@ class ProductTest extends \PHPUnit_Framework_TestCase */ public function testGetProductLinks() { - $inputLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); - $inputLink->setProductSku("Simple Product 1"); - $inputLink->setLinkType("related"); - $inputLink->setData("sku", "Simple Product 2"); - $inputLink->setData("type_id", "simple"); - $inputLink->setPosition(0); - - $outputLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); - $outputLink->setProductSku("Simple Product 1"); - $outputLink->setLinkType("related"); - $outputLink->setLinkedProductSku("Simple Product 2"); - $outputLink->setLinkedProductType("simple"); - $outputLink->setPosition(0); - - $productLinks = []; - $this->model->setData('related_products', [$inputLink]); - $productLinks[] = $outputLink; - $outputLink->setLinkType("upsell"); - $inputLink->setLinkType("upsell"); - $this->model->setData('up_sell_products', [$inputLink]); - $productLinks[] = $outputLink; - $outputLink->setLinkType("crosssell"); - $inputLink->setLinkType("crosssell"); - $this->model->setData('cross_sell_products', [$inputLink]); - $productLinks[] = $outputLink; - - $productLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); - $this->productLinkFactory->expects($this->atLeastOnce()) - ->method('create') - ->willReturn($productLink); - + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $inputRelatedLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku("Simple Product 1"); + $inputRelatedLink->setLinkType("related"); + $inputRelatedLink->setData("sku", "Simple Product 2"); + $inputRelatedLink->setData("type", "simple"); + $inputRelatedLink->setPosition(0); + + $outputRelatedLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $outputRelatedLink->setProductSku("Simple Product 1"); + $outputRelatedLink->setLinkType("related"); + $outputRelatedLink->setLinkedProductSku("Simple Product 2"); + $outputRelatedLink->setLinkedProductType("simple"); + $outputRelatedLink->setPosition(0); + + $this->entityCollectionProviderMock->expects($this->at(0)) + ->method('getCollection') + ->with($this->model, 'related') + ->willReturn([$inputRelatedLink]); + $this->entityCollectionProviderMock->expects($this->at(1)) + ->method('getCollection') + ->with($this->model, 'upsell') + ->willReturn([]); + $this->entityCollectionProviderMock->expects($this->at(2)) + ->method('getCollection') + ->with($this->model, 'crosssell') + ->willReturn([]); + $this->entityCollectionProviderMock->expects($this->at(3)) + ->method('getCollection') + ->with($this->model, 'associated') + ->willReturn([]); + + $expectedOutput = [$outputRelatedLink]; $typeInstanceMock = $this->getMock( 'Magento\ConfigurableProduct\Model\Product\Type\Simple', ["getSku"], [], '', false); $typeInstanceMock @@ -776,8 +799,13 @@ class ProductTest extends \PHPUnit_Framework_TestCase ->willReturn("Simple Product 1"); $this->model->setTypeInstance($typeInstanceMock); + $productLink1 = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $this->productLinkFactory->expects($this->at(0)) + ->method('create') + ->willReturn($productLink1); + $links = $this->model->getProductLinks(); - $this->assertEquals($links, $productLinks); + $this->assertEquals($links, $expectedOutput); } /** diff --git a/app/code/Magento/Catalog/composer.json b/app/code/Magento/Catalog/composer.json index 16e53d937b9199bb77a3828853871a6e287d4060..9aba73d735b3ff1caee1b2a7840d0a37037bb935 100644 --- a/app/code/Magento/Catalog/composer.json +++ b/app/code/Magento/Catalog/composer.json @@ -3,37 +3,37 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-indexer": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-log": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-wishlist": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-msrp": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-catalog-rule": "0.74.0-beta6", - "magento/module-product-alert": "0.74.0-beta6", - "magento/module-url-rewrite": "0.74.0-beta6", - "magento/module-catalog-url-rewrite": "0.74.0-beta6", - "magento/module-page-cache": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-indexer": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-log": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-wishlist": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-msrp": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-catalog-rule": "0.74.0-beta7", + "magento/module-product-alert": "0.74.0-beta7", + "magento/module-url-rewrite": "0.74.0-beta7", + "magento/module-catalog-url-rewrite": "0.74.0-beta7", + "magento/module-page-cache": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta6" + "magento/module-cookie": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index acd741fdbbe66d5c107a3d24ce3d99a5ec716b52..8a4efe5a2b862b4be9e489a7a9c01b186ad08b0c 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -98,6 +98,7 @@ <type name="Magento\Catalog\Model\Product"> <arguments> <argument name="catalogProductStatus" xsi:type="object">Magento\Catalog\Model\Product\Attribute\Source\Status\Proxy</argument> + <argument name="productLink" xsi:type="object">Magento\Catalog\Model\Product\Link\Proxy</argument> </arguments> </type> <type name="Magento\Catalog\Model\Resource\Product\Collection"> @@ -398,6 +399,11 @@ <argument name="validatorFile" xsi:type="object">Magento\Catalog\Model\Product\Option\Type\File\ValidatorFile\Proxy</argument> </arguments> </type> + <type name="Magento\Catalog\Model\Attribute\Config"> + <arguments> + <argument name="dataStorage" xsi:type="object">Magento\Catalog\Model\Attribute\Config\Data\Proxy</argument> + </arguments> + </type> <virtualType name="Magento\Catalog\Model\Layer\Search\Context" type="Magento\Catalog\Model\Layer\Context"> <arguments> <argument name="collectionProvider" xsi:type="object">Magento\Catalog\Model\Layer\Search\ItemCollectionProvider</argument> @@ -464,4 +470,9 @@ <type name="Magento\Catalog\Api\ProductRepositoryInterface"> <plugin name="transactionWrapper" type="\Magento\Catalog\Model\Plugin\ProductRepository\TransactionWrapper" sortOrder="-1"/> </type> + <type name="Magento\Catalog\Model\CategoryRepository"> + <arguments> + <argument name="categoryResource" xsi:type="object">Magento\Catalog\Model\Resource\Category\Proxy</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product.js index df3cc6b9694987e9e382d8e348db0fd2f95d9915..ec4e6efab5be63b5539f5a25ab5c449cebe1a04b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product.js @@ -3,14 +3,18 @@ * See COPYING.txt for license details. */ require([ - "jquery", - "prototype" -], function(jQuery){ + 'jquery' +], function ($) { + 'use strict'; window.Product = {}; + function byId(id) { + return document.getElementById(id); + } + function toogleFieldEditMode(toogleIdentifier, fieldContainer) { - if ($(toogleIdentifier).checked) { + if (byId(toogleIdentifier).checked) { enableFieldEditMode(fieldContainer); } else { disableFieldEditMode(fieldContainer); @@ -18,47 +22,53 @@ require([ } function disableFieldEditMode(fieldContainer) { - $(fieldContainer).disabled = true; - if ($(fieldContainer + '_hidden')) { - $(fieldContainer + '_hidden').disabled = true; + byId(fieldContainer).disabled = true; + + if (byId(fieldContainer + '_hidden')) { + byId(fieldContainer + '_hidden').disabled = true; } } function enableFieldEditMode(fieldContainer) { - $(fieldContainer).disabled = false; - if ($(fieldContainer + '_hidden')) { - $(fieldContainer + '_hidden').disabled = false; + byId(fieldContainer).disabled = false; + + if (byId(fieldContainer + '_hidden')) { + byId(fieldContainer + '_hidden').disabled = false; } } function onCompleteDisableInited() { - jQuery.each(jQuery('[data-disable]'), function () { - var item = jQuery(this).data('disable'); + $.each($('[data-disable]'), function () { + var item = $(this).data('disable'); disableFieldEditMode(item); }); } function onUrlkeyChanged(urlKey) { - urlKey = $(urlKey); - var hidden = urlKey.next('input[type=hidden]'); - var chbx = urlKey.next('input[type=checkbox]'); + urlKey = byId(urlKey); + var hidden = $(urlKey).next('input[type=hidden]')[0]; + var chbx = $(urlKey).next('input[type=checkbox]')[0]; var oldValue = chbx.value; - chbx.disabled = (oldValue == urlKey.value); + + chbx.disabled = (oldValue === urlKey.value); hidden.disabled = chbx.disabled; } function onCustomUseParentChanged(element) { - var useParent = (element.value == 1) ? true : false; - element.up(2).select('input', 'select', 'textarea').each(function (el) { - if (element.id != el.id) { + var useParent = (element.value === 1) ? true : false, + parent = $(element).parent().parent(); + + parent.find('input, select, textarea').each(function (i, el) { + if (element.id !== el.id) { el.disabled = useParent; } }); - element.up(2).select('img').each(function (el) { + + parent.find('img').each(function (i, el) { if (useParent) { - el.hide(); + $(el).hide(); } else { - el.show(); + $(el).show(); } }); } @@ -67,5 +77,5 @@ require([ window.onUrlkeyChanged = onUrlkeyChanged; window.toogleFieldEditMode = toogleFieldEditMode; - Event.observe(window, 'load', onCompleteDisableInited); -}); \ No newline at end of file + $(window).load(onCompleteDisableInited); +}); diff --git a/app/code/Magento/Catalog/view/base/web/js/price-box.js b/app/code/Magento/Catalog/view/base/web/js/price-box.js index 667a30836e529533ce04c77b9f5605668852b04b..eed8ac4b9752c2eabcf80175699cc778d7d491c0 100644 --- a/app/code/Magento/Catalog/view/base/web/js/price-box.js +++ b/app/code/Magento/Catalog/view/base/web/js/price-box.js @@ -190,7 +190,7 @@ define([ if (_.isEmpty(prices)) { priceHolders.each(function (index, element) { var type = $(element).data('priceType'), - amount = $(element).data('priceAmount'); + amount = parseFloat($(element).data('priceAmount')); if (type && amount) { prices[type] = { diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 15ab59aaab2b3b5e2b694f685e7d7523fcb5c565..72810dc82611f66c38e19f027215af9cd063721f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -802,7 +802,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity } } } catch (\Exception $e) { - $this->_logger->logException($e); + $this->_logger->critical($e); } return $exportData; } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php index a71fe9dcc496215b69d7573c094c6762a8be4c4d..0f68ad9e99503a7932d2407dd79bd15d55c870f5 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php @@ -13,23 +13,4 @@ namespace Magento\CatalogImportExport\Model\Import\Proxy\Product; class Resource extends \Magento\Catalog\Model\Resource\Product { - /** - * Product to category table. - * - * @return string - */ - public function getProductCategoryTable() - { - return $this->_productCategoryTable; - } - - /** - * Product to website table. - * - * @return string - */ - public function getProductWebsiteTable() - { - return $this->_productWebsiteTable; - } } diff --git a/app/code/Magento/CatalogImportExport/composer.json b/app/code/Magento/CatalogImportExport/composer.json index ee8f34355558e63ab22dc08089041e4bdc99c3a4..83d1e2e075da3a7a18b94418bb619feb0d8f86ad 100644 --- a/app/code/Magento/CatalogImportExport/composer.json +++ b/app/code/Magento/CatalogImportExport/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-import-export": "0.74.0-beta6", - "magento/module-indexer": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-import-export": "0.74.0-beta7", + "magento/module-indexer": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "ext-ctype": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogInventory/Api/Data/StockItemInterface.php b/app/code/Magento/CatalogInventory/Api/Data/StockItemInterface.php index 46163c26be6d3df33831a35e9344333ffeaef7ef..0a620ce1562d529959ce09af000bc2f3b9923b7a 100644 --- a/app/code/Magento/CatalogInventory/Api/Data/StockItemInterface.php +++ b/app/code/Magento/CatalogInventory/Api/Data/StockItemInterface.php @@ -55,7 +55,7 @@ interface StockItemInterface extends ExtensibleDataInterface const CUSTOMER_GROUP_ID = 'customer_group_id'; /** - * @return int + * @return int|null */ public function getItemId(); @@ -66,7 +66,7 @@ interface StockItemInterface extends ExtensibleDataInterface public function setItemId($itemId); /** - * @return int + * @return int|null */ public function getProductId(); @@ -79,7 +79,7 @@ interface StockItemInterface extends ExtensibleDataInterface /** * Retrieve Website Id * - * @return int + * @return int|null */ public function getWebsiteId(); @@ -94,7 +94,7 @@ interface StockItemInterface extends ExtensibleDataInterface /** * Retrieve stock identifier * - * @return int + * @return int|null */ public function getStockId(); diff --git a/app/code/Magento/CatalogInventory/Model/Plugin/AfterProductLoad.php b/app/code/Magento/CatalogInventory/Model/Plugin/AfterProductLoad.php new file mode 100644 index 0000000000000000000000000000000000000000..3d6c9d404afe0e0e4594ef8f467c630575c69fab --- /dev/null +++ b/app/code/Magento/CatalogInventory/Model/Plugin/AfterProductLoad.php @@ -0,0 +1,51 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogInventory\Model\Plugin; + +class AfterProductLoad +{ + /** + * @var \Magento\CatalogInventory\Api\StockRegistryInterface + */ + protected $stockRegistry; + + /** + * @var \Magento\Catalog\Api\Data\ProductExtensionFactory + */ + protected $productExtensionFactory; + + /** + * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry + * @param \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory + */ + public function __construct( + \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, + \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory + ) { + $this->stockRegistry = $stockRegistry; + $this->productExtensionFactory = $productExtensionFactory; + } + + /** + * Add stock item information to the product's extension attributes + * + * @param \Magento\Catalog\Model\Product $product + * @return \Magento\Catalog\Model\Product + */ + public function afterLoad(\Magento\Catalog\Model\Product $product) + { + $productExtension = $product->getExtensionAttributes(); + if ($productExtension === null) { + $productExtension = $this->productExtensionFactory->create(); + } + // stockItem := \Magento\CatalogInventory\Api\Data\StockItemInterface + $productExtension->setStockItem($this->stockRegistry->getStockItem($product->getId())); + $product->setExtensionAttributes($productExtension); + return $product; + } +} diff --git a/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php b/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php new file mode 100644 index 0000000000000000000000000000000000000000..0b222de117c9e84cb9aea4c009889f57ccbb8c80 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php @@ -0,0 +1,95 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogInventory\Model\Plugin; + +class AroundProductRepositorySave +{ + /** + * @var \Magento\CatalogInventory\Api\StockRegistryInterface + */ + protected $stockRegistry; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + + /** + * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + */ + public function __construct( + \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, + \Magento\Store\Model\StoreManagerInterface $storeManager + ) { + $this->stockRegistry = $stockRegistry; + $this->storeManager = $storeManager; + } + + /** + * @param \Magento\Catalog\Api\ProductRepositoryInterface $subject + * @param callable $proceed + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param bool $saveOptions + * @return \Magento\Catalog\Api\Data\ProductInterface + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function aroundSave( + \Magento\Catalog\Api\ProductRepositoryInterface $subject, + \Closure $proceed, + \Magento\Catalog\Api\Data\ProductInterface $product, + $saveOptions = false + ) { + /** @var \Magento\Catalog\Api\Data\ProductInterface $result */ + $result = $proceed($product, $saveOptions); + + /* @var \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem */ + $stockItem = $this->getStockItemToBeUpdated($product); + if ($stockItem == null) { + return $result; + } + + // set fields that the customer should not care about + $stockItem->setProductId($result->getId()); + $stockItem->setWebsiteId($this->storeManager->getStore($result->getStoreId())->getWebsiteId()); + + $this->stockRegistry->updateStockItemBySku($result->getSku(), $stockItem); + + // since we just saved a portion of the product, force a reload of it before returning it + return $subject->get($result->getSku(), false, $result->getStoreId(), true); + } + + /** + * Return the stock item that needs to be updated. + * If the stock item does not need to be updated, return null. + * + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return \Magento\CatalogInventory\Api\Data\StockItemInterface|null + */ + protected function getStockItemToBeUpdated($product) + { + // from the API, all the data we care about will exist as extension attributes of the original product + $extendedAttributes = $product->getExtensionAttributes(); + if ($extendedAttributes !== null) { + $stockItem = $extendedAttributes->getStockItem(); + if ($stockItem != null) { + return $stockItem; + } + } + + // we have no new stock item information to update, however we need to ensure that the product does have some + // stock item information present. On a newly created product, it will not have any stock item info. + $stockItem = $this->stockRegistry->getStockItem($product->getId()); + if ($stockItem->getItemId() != null) { + // we already have stock item info, so we return null since nothing more needs to be updated + return null; + } + + return $stockItem; + } +} diff --git a/app/code/Magento/CatalogInventory/Model/Stock/Item.php b/app/code/Magento/CatalogInventory/Model/Stock/Item.php index cb622e904c6bbab1838275d66a5f9129e6640a24..15fb84875aafeac95108233e7f4ea482fc295a26 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/Item.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/Item.php @@ -239,11 +239,11 @@ class Item extends AbstractExtensibleModel implements StockItemInterface } /** - * @return int Timestamp + * @return string Timestamp */ public function getLowStockDate() { - return (int) $this->_getData(static::LOW_STOCK_DATE); + return $this->_getData(static::LOW_STOCK_DATE); } /** diff --git a/app/code/Magento/CatalogInventory/Model/StockManagement.php b/app/code/Magento/CatalogInventory/Model/StockManagement.php index 1f50b8b5dceaa3b64ff14c83044ac6e62f7e85cb..3d5fee6d9cef90eb8bfcf98d78b6c45e68c0bca2 100644 --- a/app/code/Magento/CatalogInventory/Model/StockManagement.php +++ b/app/code/Magento/CatalogInventory/Model/StockManagement.php @@ -84,7 +84,7 @@ class StockManagement implements StockManagementInterface $orderedQty = $items[$productId]; $stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId); $canSubtractQty = $stockItem->getItemId() && $this->canSubtractQty($stockItem); - if (!$canSubtractQty || !$this->stockConfiguration->isQty($this->getProductType($productId))) { + if (!$canSubtractQty || !$this->stockConfiguration->isQty($lockedItemRecord['type_id'])) { continue; } if (!$stockItem->hasAdminArea() diff --git a/app/code/Magento/CatalogInventory/Model/StockRegistry.php b/app/code/Magento/CatalogInventory/Model/StockRegistry.php index fefbf9f34899f031a374d551e390b24235d3f9c0..f32aeb2104b686091e06120271c462ec33542f08 100644 --- a/app/code/Magento/CatalogInventory/Model/StockRegistry.php +++ b/app/code/Magento/CatalogInventory/Model/StockRegistry.php @@ -15,6 +15,8 @@ use Magento\CatalogInventory\Model\Spi\StockRegistryProviderInterface; /** * Class StockRegistry + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class StockRegistry implements StockRegistryInterface { @@ -185,9 +187,7 @@ class StockRegistry implements StockRegistryInterface $origStockItem = $this->getStockItem($productId, $websiteId); $data = $stockItem->getData(); if ($origStockItem->getItemId()) { - if (isset($data['item_id'])) { - unset($data['item_id']); - } + unset($data['item_id']); } $origStockItem->addData($data); $origStockItem->setProductId($productId); diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AfterProductLoadTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AfterProductLoadTest.php new file mode 100644 index 0000000000000000000000000000000000000000..77b8985cac84c3d21bb9eeb7a598ea9138c366d6 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AfterProductLoadTest.php @@ -0,0 +1,104 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\CatalogInventory\Test\Unit\Model\Plugin; + +class AfterProductLoadTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\CatalogInventory\Model\Plugin\AfterProductLoad + */ + protected $plugin; + + /** + * @var \Magento\Catalog\Api\Data\ProductInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \Magento\Catalog\Api\Data\ProductExtensionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionFactoryMock; + + /** + * @var \Magento\Catalog\Api\Data\ProductExtension|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionMock; + + protected function setUp() + { + $stockRegistryMock = $this->getMock('\Magento\CatalogInventory\Api\StockRegistryInterface'); + $this->productExtensionFactoryMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtensionFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->plugin = new \Magento\CatalogInventory\Model\Plugin\AfterProductLoad( + $stockRegistryMock, + $this->productExtensionFactoryMock + ); + + $productId = 5494; + $stockItemMock = $this->getMock('\Magento\CatalogInventory\Api\Data\StockItemInterface'); + + $stockRegistryMock->expects($this->once()) + ->method('getStockItem') + ->with($productId) + ->willReturn($stockItemMock); + + $this->productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['setStockItem']) + ->getMock(); + $this->productExtensionMock->expects($this->once()) + ->method('setStockItem') + ->with($stockItemMock) + ->willReturnSelf(); + + $this->productMock = $this->getMockBuilder('\Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + $this->productMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($this->productExtensionMock) + ->willReturnSelf(); + $this->productMock->expects(($this->once())) + ->method('getId') + ->will($this->returnValue($productId)); + } + + public function testAfterLoad() + { + // test when extension attributes are not (yet) present in the product + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn(null); + $this->productExtensionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->productExtensionMock); + + $this->assertEquals( + $this->productMock, + $this->plugin->afterLoad($this->productMock) + ); + } + + public function testAfterLoadWithExistingExtensionAttributes() + { + // test when extension attributes already exist + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionFactoryMock->expects($this->never()) + ->method('create'); + + $this->assertEquals( + $this->productMock, + $this->plugin->afterLoad($this->productMock) + ); + } +} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php new file mode 100644 index 0000000000000000000000000000000000000000..95560e7ce7be3144937120e89eb40f41484b7586 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php @@ -0,0 +1,176 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\CatalogInventory\Test\Unit\Model\Plugin; + +class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\CatalogInventory\Model\Plugin\AroundProductRepositorySave + */ + protected $plugin; + + /** + * @var \Magento\CatalogInventory\Api\Data\StockItemInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $stockItemMock; + + /** + * @var \Magento\Catalog\Api\Data\ProductInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \Magento\Catalog\Api\Data\ProductInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $savedProductMock; + + /** + * @var \Magento\CatalogInventory\Api\StockRegistryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $stockRegistry; + + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManager; + + /** + * @var \Magento\Catalog\Api\Data\ProductExtension|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionMock; + + /** + * @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productRepositoryMock; + + /** + * @var \Closure + */ + protected $closureMock; + + public function setUp() + { + $this->stockRegistry = $this->getMock('\Magento\CatalogInventory\Api\StockRegistryInterface'); + $this->storeManager = $this->getMock('\Magento\Store\Model\StoreManagerInterface'); + + $this->plugin = new \Magento\CatalogInventory\Model\Plugin\AroundProductRepositorySave( + $this->stockRegistry, + $this->storeManager + ); + + $this->productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['getStockItem']) + ->getMock(); + $this->productRepositoryMock = $this->getMock('Magento\Catalog\Api\ProductRepositoryInterface'); + $this->productMock = $this->getMock('\Magento\Catalog\Api\Data\ProductInterface'); + $this->savedProductMock = $this->getMock('\Magento\Catalog\Api\Data\ProductInterface'); + $this->closureMock = function () { + return $this->savedProductMock; + }; + $this->stockItemMock = $this->getMock('\Magento\CatalogInventory\Api\Data\StockItemInterface'); + } + + public function testAroundSaveWhenProductHasNoStockItemNeedingToBeUpdated() + { + // pretend we have no extension attributes at all + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn(null); + $this->productExtensionMock->expects($this->never())->method('getStockItem'); + + // pretend that the product already has existing stock item information + $this->stockRegistry->expects($this->once())->method('getStockItem')->willReturn($this->stockItemMock); + $this->stockItemMock->expects($this->once())->method('getItemId')->willReturn(1); + $this->stockItemMock->expects($this->never())->method('setProductId'); + $this->stockItemMock->expects($this->never())->method('setWebsiteId'); + + // expect that there are no changes to the existing stock item information + $this->assertEquals( + $this->savedProductMock, + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + public function testAroundSaveWhenProductHasNoPersistentStockItemInfo() + { + // pretend we do have extension attributes, but none for 'stock_item' + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getStockItem') + ->willReturn(null); + + $storeMock = $this->getMockBuilder('\Magento\Store\Model\Store') + ->disableOriginalConstructor()->getMock(); + $storeMock->expects($this->once())->method('getWebsiteId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock); + + $this->stockRegistry->expects($this->once())->method('getStockItem')->willReturn($this->stockItemMock); + $this->stockRegistry->expects($this->once())->method('updateStockItemBySku'); + + $this->stockItemMock->expects($this->once())->method('getItemId')->willReturn(null); + $this->stockItemMock->expects($this->once())->method('setProductId'); + $this->stockItemMock->expects($this->once())->method('setWebsiteId'); + + $newProductMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface') + ->disableOriginalConstructor()->getMock(); + $this->productRepositoryMock->expects($this->once())->method('get')->willReturn($newProductMock); + + $this->assertEquals( + $newProductMock, + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + public function testAroundSave() + { + $productId = 5494; + $websiteId = 1; + $storeId = 2; + $sku = 'my product that needs saving'; + + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getStockItem') + ->willReturn($this->stockItemMock); + + $storeMock = $this->getMockBuilder('\Magento\Store\Model\Store') + ->disableOriginalConstructor()->getMock(); + $storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId); + $this->storeManager->expects($this->once())->method('getStore')->with($storeId)->willReturn($storeMock); + + $this->savedProductMock->expects(($this->once()))->method('getId')->willReturn($productId); + $this->savedProductMock->expects(($this->atLeastOnce()))->method('getStoreId')->willReturn($storeId); + $this->savedProductMock->expects($this->atLeastOnce())->method('getSku')->willReturn($sku); + + $this->stockItemMock->expects($this->once())->method('setProductId')->with($productId); + $this->stockItemMock->expects($this->once())->method('setWebsiteId')->with($websiteId); + + $this->stockRegistry->expects($this->once()) + ->method('updateStockItemBySku') + ->with($sku, $this->stockItemMock); + + $newProductMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface') + ->disableOriginalConstructor()->getMock(); + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($sku, false, $storeId, true) + ->willReturn($newProductMock); + + $this->assertEquals( + $newProductMock, + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } +} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/ItemTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/ItemTest.php index 20de61fbf3ba19c6851e47bc016e3ee38e82d9eb..f6cfa8b4e7e6643d3b4df80ae83fe79bd57dd0fc 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/ItemTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/ItemTest.php @@ -395,4 +395,12 @@ class ItemTest extends \PHPUnit_Framework_TestCase [0, $this->storeId], ]; } + + public function testGetLowStockDate() + { + // ensure we do *not* return '2015' due to casting to an int + $date = '2015-4-17'; + $this->item->setLowStockDate($date); + $this->assertEquals($date, $this->item->getLowStockDate()); + } } diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index 129c2285172ca06dabdd98cb51dcc1a6ba9fdad7..b7209d2df90f07c288bdaa1eca809222777c6678 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-indexer": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-indexer": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogInventory/etc/di.xml b/app/code/Magento/CatalogInventory/etc/di.xml index 11c98534f732718a84bb3cde28379c3f76137b61..b1ad4a03847bbd997e93dc255b0d7de325f11f9d 100644 --- a/app/code/Magento/CatalogInventory/etc/di.xml +++ b/app/code/Magento/CatalogInventory/etc/di.xml @@ -52,4 +52,15 @@ <type name="Magento\Catalog\Block\Product\View"> <plugin name="quantityValidators" type="Magento\CatalogInventory\Block\Plugin\ProductView" /> </type> + <type name="Magento\CatalogInventory\Model\Configuration"> + <arguments> + <argument name="config" xsi:type="object">Magento\Catalog\Model\ProductTypes\Config\Proxy</argument> + </arguments> + </type> + <type name="Magento\Catalog\Model\Product"> + <plugin name="catalogInventoryAfterLoad" type="\Magento\CatalogInventory\Model\Plugin\AfterProductLoad"/> + </type> + <type name="Magento\Catalog\Api\ProductRepositoryInterface"> + <plugin name="catalogInventoryAroundSave" type="\Magento\CatalogInventory\Model\Plugin\AroundProductRepositorySave"/> + </type> </config> diff --git a/app/code/Magento/CatalogInventory/etc/service_data_attributes.xml b/app/code/Magento/CatalogInventory/etc/service_data_attributes.xml new file mode 100644 index 0000000000000000000000000000000000000000..587b98b401a0981d8ca14b75242f0adac67312a2 --- /dev/null +++ b/app/code/Magento/CatalogInventory/etc/service_data_attributes.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> + <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface"> + <resources> + <resource ref="Magento_CatalogInventory::cataloginventory"/> + </resources> + </attribute> + </extension_attributes> +</config> diff --git a/app/code/Magento/CatalogRule/composer.json b/app/code/Magento/CatalogRule/composer.json index 321bbcd7334b631b6f630452474b2ae25f5a265c..b3192cfcc8459c4f74fa8c68076c255add2719b3 100644 --- a/app/code/Magento/CatalogRule/composer.json +++ b/app/code/Magento/CatalogRule/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-rule": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-indexer": "0.74.0-beta6", - "magento/module-import-export": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-rule": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-indexer": "0.74.0-beta7", + "magento/module-import-export": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json index d9f2822e173203097515ba797209fdbb4a4c8a64..39e60cdc03a9c5e15623e4744e874cb04360f601 100644 --- a/app/code/Magento/CatalogSearch/composer.json +++ b/app/code/Magento/CatalogSearch/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-search": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-indexer": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-search": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-indexer": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogUrlRewrite/composer.json b/app/code/Magento/CatalogUrlRewrite/composer.json index 2488990a45e7570de05a47be2802787cb2fe1395..2e9cc77143f5017b3fc59b6257edd8789592fcef 100644 --- a/app/code/Magento/CatalogUrlRewrite/composer.json +++ b/app/code/Magento/CatalogUrlRewrite/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-catalog-import-export": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-import-export": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-url-rewrite": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-catalog-import-export": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-import-export": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-url-rewrite": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogWidget/composer.json b/app/code/Magento/CatalogWidget/composer.json index e92c896cb1a574e1aa912d5cc378bb8c70aead25..6600bf5ff65cec1c7f2915dcceb4d5812048bcdb 100644 --- a/app/code/Magento/CatalogWidget/composer.json +++ b/app/code/Magento/CatalogWidget/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-rule": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-wishlist": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-rule": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-wishlist": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Centinel/composer.json b/app/code/Magento/Centinel/composer.json index 584771858a87c0b5d497fd4ff33d11d890b28892..fba6a6e8c1b5af2c4b3f933e8ca57cd319447f4f 100644 --- a/app/code/Magento/Centinel/composer.json +++ b/app/code/Magento/Centinel/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php index 04141e448fec992be6bc53f0afa82b41d6dedd2d..7249f26f18540c606d9716bbc55b17ef2312adc8 100644 --- a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php +++ b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php @@ -5,6 +5,7 @@ */ namespace Magento\Checkout\Controller\Onepage; +use Magento\Framework\Object; use Magento\Framework\Exception\PaymentException; class SaveOrder extends \Magento\Checkout\Controller\Onepage @@ -26,16 +27,17 @@ class SaveOrder extends \Magento\Checkout\Controller\Onepage return $this->_ajaxRedirectResponse(); } - $result = []; + $result = new Object(); try { $agreementsValidator = $this->_objectManager->get('Magento\Checkout\Model\Agreements\AgreementsValidator'); if (!$agreementsValidator->isValid(array_keys($this->getRequest()->getPost('agreement', [])))) { - $result['success'] = false; - $result['error'] = true; - $result['error_messages'] = __( - 'Please agree to all the terms and conditions before placing the order.' + $result->setData('success', false); + $result->setData('error', true); + $result->setData( + 'error_messages', + __('Please agree to all the terms and conditions before placing the order.') ); - return $this->resultJsonFactory->create()->setData($result); + return $this->resultJsonFactory->create()->setData($result->getData()); } $data = $this->getRequest()->getPost('payment', []); @@ -54,25 +56,34 @@ class SaveOrder extends \Magento\Checkout\Controller\Onepage $this->getOnepage()->saveOrder(); $redirectUrl = $this->getOnepage()->getCheckout()->getRedirectUrl(); - $result['success'] = true; - $result['error'] = false; + $result->setData('success', true); + $result->setData('error', false); } catch (PaymentException $e) { $message = $e->getMessage(); if (!empty($message)) { - $result['error_messages'] = $message; + $result->setData('error_messages', $message); } - $result['goto_section'] = 'payment'; - $result['update_section'] = ['name' => 'payment-method', 'html' => $this->_getPaymentMethodsHtml()]; + $result->setData('goto_section', 'payment'); + $result->setData( + 'update_section', + [ + 'name' => 'payment-method', + 'html' => $this->_getPaymentMethodsHtml() + ] + ); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->_objectManager->get('Magento\Checkout\Helper\Data') ->sendPaymentFailedEmail($this->getOnepage()->getQuote(), $e->getMessage()); - $result['success'] = false; - $result['error'] = true; - $result['error_messages'] = $e->getMessage(); + $result->setData( + 'success', + false + ); + $result->setData('error', true); + $result->setData('error_messages', $e->getMessage()); $gotoSection = $this->getOnepage()->getCheckout()->getGotoSection(); if ($gotoSection) { - $result['goto_section'] = $gotoSection; + $result->setData('goto_section', $gotoSection); $this->getOnepage()->getCheckout()->setGotoSection(null); } @@ -80,10 +91,13 @@ class SaveOrder extends \Magento\Checkout\Controller\Onepage if ($updateSection) { if (isset($this->_sectionUpdateFunctions[$updateSection])) { $updateSectionFunction = $this->_sectionUpdateFunctions[$updateSection]; - $result['update_section'] = [ - 'name' => $updateSection, - 'html' => $this->{$updateSectionFunction}(), - ]; + $result->setData( + 'update_section', + [ + 'name' => $updateSection, + 'html' => $this->{$updateSectionFunction}(), + ] + ); } $this->getOnepage()->getCheckout()->setUpdateSection(null); } @@ -91,18 +105,29 @@ class SaveOrder extends \Magento\Checkout\Controller\Onepage $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->_objectManager->get('Magento\Checkout\Helper\Data') ->sendPaymentFailedEmail($this->getOnepage()->getQuote(), $e->getMessage()); - $result['success'] = false; - $result['error'] = true; - $result['error_messages'] = __('Something went wrong processing your order. Please try again later.'); + $result->setData('success', false); + $result->setData('error', true); + $result->setData( + 'error_messages', + __('Something went wrong processing your order. Please try again later.') + ); } /** * when there is redirect to third party, we don't want to save order yet. * we will save the order in return action. */ if (isset($redirectUrl)) { - $result['redirect'] = $redirectUrl; + $result->setData('redirect', $redirectUrl); } - return $this->resultJsonFactory->create()->setData($result); + $this->_eventManager->dispatch( + 'checkout_controller_onepage_saveOrder', + [ + 'result' => $result, + 'action' => $this + ] + ); + + return $this->resultJsonFactory->create()->setData($result->getData()); } } diff --git a/app/code/Magento/Checkout/Model/Session.php b/app/code/Magento/Checkout/Model/Session.php index 0f7d18e41355b5ffbae94f02f0f6272485d59cbd..da634e082756d1e8be81769a6af6dc32a6874fbe 100644 --- a/app/code/Magento/Checkout/Model/Session.php +++ b/app/code/Magento/Checkout/Model/Session.php @@ -90,6 +90,7 @@ class Session extends \Magento\Framework\Session\SessionManager * @param \Magento\Framework\Session\StorageInterface $storage * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory + * @param \Magento\Framework\App\State $appState * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Quote\Model\QuoteRepository $quoteRepository @@ -97,6 +98,7 @@ class Session extends \Magento\Framework\Session\SessionManager * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository + * @throws \Magento\Framework\Exception\SessionException * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -108,6 +110,7 @@ class Session extends \Magento\Framework\Session\SessionManager \Magento\Framework\Session\StorageInterface $storage, \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory, + \Magento\Framework\App\State $appState, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Customer\Model\Session $customerSession, \Magento\Quote\Model\QuoteRepository $quoteRepository, @@ -131,9 +134,9 @@ class Session extends \Magento\Framework\Session\SessionManager $validator, $storage, $cookieManager, - $cookieMetadataFactory + $cookieMetadataFactory, + $appState ); - $this->start(); } /** diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/SaveOrderTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/SaveOrderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cef6ff863cc8d50289d6d12c92e9bfc4421f07e6 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/SaveOrderTest.php @@ -0,0 +1,322 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Test\Unit\Controller\Onepage; + +use Magento\Checkout\Controller\Onepage\SaveOrder; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +/** + * Class SaveOrderTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class SaveOrderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var SaveOrder + */ + protected $controller; + + /** + * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $formKeyValidatorMock; + + /** + * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $requestMock; + + /** + * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $responseMock; + + /** + * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $objectManagerMock; + + /** + * @var \Magento\Framework\Controller\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRedirectFactoryMock; + + /** + * @var \Magento\Framework\Controller\Result\RawFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRawFactoryMock; + + /** + * @var \Magento\Framework\Controller\Result\JsonFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultJsonFactoryMock; + + /** + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + + /** + * @var \Magento\Checkout\Model\Type\Onepage|\PHPUnit_Framework_MockObject_MockObject + */ + protected $onepageMock; + + /** + * @var \Magento\Checkout\Model\Agreements\AgreementsValidator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $agreementsValidatorMock; + + /** + * @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject + */ + protected $quoteMock; + + /** + * Set up + * + * @return void + */ + protected function setUp() + { + $helper = new ObjectManager($this); + + $contextMock = $this->getMockBuilder('Magento\Framework\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->requestMock = $this->getMockBuilder('Magento\Framework\App\RequestInterface') + ->disableOriginalConstructor() + ->setMethods(['getPost']) + ->getMockForAbstractClass(); + $this->responseMock = $this->getMockBuilder('Magento\Framework\App\ResponseInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->formKeyValidatorMock = $this->getMockBuilder('Magento\Framework\Data\Form\FormKey\Validator') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\Result\RedirectFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRawFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\Result\RawFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultJsonFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\Result\JsonFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->eventManagerMock = $this->getMockBuilder('Magento\Framework\Event\ManagerInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->onepageMock = $this->getMockBuilder('Magento\Checkout\Model\Type\Onepage') + ->disableOriginalConstructor() + ->getMock(); + $this->agreementsValidatorMock = $this->getMockBuilder('Magento\Checkout\Model\Agreements\AgreementsValidator') + ->disableOriginalConstructor() + ->getMock(); + $this->quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + + $contextMock->expects($this->once()) + ->method('getRequest') + ->willReturn($this->requestMock); + $contextMock->expects($this->once()) + ->method('getResponse') + ->willReturn($this->responseMock); + $contextMock->expects($this->once()) + ->method('getObjectManager') + ->willReturn($this->objectManagerMock); + $contextMock->expects($this->once()) + ->method('getResultRedirectFactory') + ->willReturn($this->resultRedirectFactoryMock); + $contextMock->expects($this->once()) + ->method('getEventManager') + ->willReturn($this->eventManagerMock); + + $this->controller = $helper->getObject( + 'Magento\Checkout\Controller\Onepage\SaveOrder', + [ + 'context' => $contextMock, + 'formKeyValidator' => $this->formKeyValidatorMock, + 'resultRawFactory' => $this->resultRawFactoryMock, + 'resultJsonFactory' => $this->resultJsonFactoryMock, + ] + ); + } + + /** + * Test method execution _expireAjax (call hasItems === false) + * + * @return void + */ + protected function expireAjaxFlowHasItemsFalse() + { + $this->onepageMock->expects($this->atLeastOnce()) + ->method('getQuote') + ->willReturn($this->quoteMock); + + $this->quoteMock->expects($this->once()) + ->method('hasItems') + ->willReturn(false); + $this->quoteMock->expects($this->never()) + ->method('getHasError') + ->willReturn(true); + $this->quoteMock->expects($this->never()) + ->method('validateMinimumAmount') + ->willReturn(false); + + $this->requestMock->expects($this->never()) + ->method('getActionName'); + } + + /** + * Test for execute method + * + * @return void + */ + public function testExecuteWithSuccessOrderSave() + { + $testData = $this->getExecuteWithSuccessOrderSaveTestData(); + + + $redirectMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + $paymentMock = $this->getMockBuilder('Magento\Quote\Model\Quote\Payment') + ->disableOriginalConstructor() + ->getMock(); + $checkoutMock = $this->getMockBuilder('Magento\Checkout\Model\Session') + ->disableOriginalConstructor() + ->setMethods(['getRedirectUrl']) + ->getMock(); + $resultJsonMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); + + $redirectMock->expects($this->never()) + ->method('setPath') + ->with('*/*/') + ->willReturn('redirect'); + + $this->formKeyValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->requestMock) + ->willReturn(true); + + $this->resultRedirectFactoryMock->expects($this->never()) + ->method('create') + ->willReturn($redirectMock); + + $this->objectManagerMock->expects($this->atLeastOnce()) + ->method('get') + ->willReturnMap($testData['objectManager.get']); + + // call _expireAjax method + $this->expireAjaxFlowHasItemsFalse(); + + $this->requestMock->expects($this->atLeastOnce()) + ->method('getPost') + ->willReturnMap($testData['request.getPost']); + + $this->agreementsValidatorMock->expects($this->once()) + ->method('isValid') + ->with($testData['agreementsValidator.isValid']) + ->willReturn(true); + + $this->quoteMock->expects($this->atLeastOnce()) + ->method('getPayment') + ->willReturn($paymentMock); + + $paymentMock->expects($this->once()) + ->method('setQuote') + ->with($this->quoteMock); + $paymentMock->expects($this->once()) + ->method('importData') + ->with($testData['payment.importData']); + + $this->onepageMock->expects($this->once()) + ->method('saveOrder'); + $this->onepageMock->expects($this->once()) + ->method('getCheckout') + ->willReturn($checkoutMock); + + $checkoutMock->expects($this->once()) + ->method('getRedirectUrl') + ->willReturn(null); + + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->withConsecutive( + $this->equalTo('checkout_controller_onepage_saveOrder'), + $this->countOf(2) + ); + + $this->resultJsonFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($resultJsonMock); + + $resultJsonMock->expects($this->once()) + ->method('setData') + ->with($testData['resultJson.setData']) + ->willReturnSelf(); + + $this->assertEquals($resultJsonMock, $this->controller->execute()); + } + + /** + * Get data for test testExecuteWithSuccessOrderSave + * + * @return array + */ + protected function getExecuteWithSuccessOrderSaveTestData() + { + $data = [ + 'payment-key-1' => 'payment-value-1', + 'checks' => [ + \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT, + \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY, + \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY, + \Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX, + \Magento\Payment\Model\Method\AbstractMethod::CHECK_ZERO_TOTAL, + ] + ]; + $testKey = 'test-key-1'; + + return [ + 'resultJson.setData' => [ + 'success' => 1, + 'error' => false + ], + 'request.getPost' => [ + [ + 'agreement', + [], + [ + $testKey => 'test-value-1' + ] + ], + [ + 'payment', + [], + $data + ], + ], + 'payment.importData' => $data, + 'agreementsValidator.isValid' => [$testKey], + 'objectManager.get' => [ + ['Magento\Checkout\Model\Type\Onepage', $this->onepageMock], + ['Magento\Checkout\Model\Agreements\AgreementsValidator', $this->agreementsValidatorMock], + ] + ]; + } +} diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json index 266290632764108d9de90c7d0d6a60a447173e5e..8d4be858de464bba4a902109399ecb0da8c843c6 100644 --- a/app/code/Magento/Checkout/composer.json +++ b/app/code/Magento/Checkout/composer.json @@ -3,32 +3,32 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-payment": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-gift-message": "0.74.0-beta6", - "magento/module-wishlist": "0.74.0-beta6", - "magento/module-page-cache": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-msrp": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-ui": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-payment": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-gift-message": "0.74.0-beta7", + "magento/module-wishlist": "0.74.0-beta7", + "magento/module-page-cache": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-msrp": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-ui": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta6" + "magento/module-cookie": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js index d3c3a264b88d814fd8123aa84bc1df10d3828aa6..31e16ff05c81bd932e7250420acce9e270f46aa4 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js @@ -60,11 +60,13 @@ define([ * @private */ _isOverflowed: function() { - var list = $(this.options.minicart.list); + var list = $(this.options.minicart.list), + cssOverflowClass = 'overflowed'; + if (this.scrollHeight > list.innerHeight()) { - list.parent().addClass('overflowed'); + list.parent().addClass(cssOverflowClass); } else { - list.parent().removeClass('overflowed'); + list.parent().removeClass(cssOverflowClass); } }, @@ -238,9 +240,9 @@ define([ this.scrollHeight = 0; target.children().each(function() { if (counter-- > 0) { - height += $(this).height() - 15; + height += $(this).height(); } - self.scrollHeight += $(this).height() - 15; + self.scrollHeight += $(this).height(); }); target.remove(); diff --git a/app/code/Magento/CheckoutAgreements/composer.json b/app/code/Magento/CheckoutAgreements/composer.json index 4693f5b11aa25b57cde6a425594a965b1355de7f..4d3341593e7fd0dce401014d7bac7ab32909f36f 100644 --- a/app/code/Magento/CheckoutAgreements/composer.json +++ b/app/code/Magento/CheckoutAgreements/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php b/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php index fed2f67da6f177806559e463deb8fda56a2fbb3f..11a83c181d64f504d267524440423a30c90b2970 100644 --- a/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php +++ b/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php @@ -81,7 +81,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended if ($element->getValue()) { $block = $this->_blockFactory->create()->load($element->getValue()); if ($block->getId()) { - $chooser->setLabel($block->getTitle()); + $chooser->setLabel($this->escapeHtml($block->getTitle())); } } diff --git a/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php b/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php index addaf3f4926b8e05f48833b16e540eb73ad295ef..54c169c890a9b8f8901203bff0a9a3a6d4e69275 100644 --- a/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php +++ b/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php @@ -98,7 +98,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended if ($element->getValue()) { $page = $this->_pageFactory->create()->load((int)$element->getValue()); if ($page->getId()) { - $chooser->setLabel($page->getTitle()); + $chooser->setLabel($this->escapeHtml($page->getTitle())); } } diff --git a/app/code/Magento/Cms/Controller/Adminhtml/AbstractMassDelete.php b/app/code/Magento/Cms/Controller/Adminhtml/AbstractMassDelete.php index defddb18779229876ae60ca59e9b40491885aedf..68cf470787c9c520135bf878c674abd922414aae 100755 --- a/app/code/Magento/Cms/Controller/Adminhtml/AbstractMassDelete.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/AbstractMassDelete.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -21,7 +20,7 @@ class AbstractMassDelete extends \Magento\Backend\App\Action /** * Redirect url */ - const REDIRECT_URL = '*/*/index'; + const REDIRECT_URL = '*/*/'; /** * Resource collection @@ -45,17 +44,17 @@ class AbstractMassDelete extends \Magento\Backend\App\Action */ public function execute() { - $data = $this->getRequest()->getParam('massaction', '[]'); - $data = json_decode($data, true); + $selected = $this->getRequest()->getParam('selected'); + $excluded = $this->getRequest()->getParam('excluded'); - if (isset($data['all_selected']) && $data['all_selected'] === true) { - if (!empty($data['excluded'])) { - $this->excludedDelete($data['excluded']); + if (isset($excluded)) { + if (!empty($excluded)) { + $this->excludedDelete($excluded); } else { $this->deleteAll(); } - } elseif (!empty($data['selected'])) { - $this->selectedDelete($data['selected']); + } elseif (!empty($selected)) { + $this->selectedDelete($selected); } else { $this->messageManager->addError(__('Please select item(s).')); } diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php index a87024f3ea1e622f46e7f1d540e5f9081932bcaf..b255b784a1ac9358e53238425db74b889432eb99 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Cms/Model/Block/DataProvider.php b/app/code/Magento/Cms/Model/Block/DataProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..71994a060b0812b0997fc3c4b026e5ae2b3c206c --- /dev/null +++ b/app/code/Magento/Cms/Model/Block/DataProvider.php @@ -0,0 +1,221 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Model\Block; + +use Magento\Cms\Model\Resource\Block\Collection; +use Magento\Cms\Model\Resource\Block\CollectionFactory; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; + +/** + * Class DataProvider + */ +class DataProvider implements DataProviderInterface +{ + /** + * @var string + */ + protected $primaryFieldName; + + /** + * @var string + */ + protected $requestFieldName; + + /** + * @var CollectionFactory + */ + protected $collectionFactory; + + /** + * @var Collection + */ + protected $collection; + + /** + * Provider configuration data + * + * @var array + */ + protected $data = []; + + /** + * @param string $primaryFieldName + * @param string $requestFieldName + * @param CollectionFactory $collectionFactory + * @param array $meta + * @param array $data + */ + public function __construct( + $primaryFieldName, + $requestFieldName, + CollectionFactory $collectionFactory, + array $meta = [], + array $data = [] + ) { + $this->primaryFieldName = $primaryFieldName; + $this->requestFieldName = $requestFieldName; + $this->collection = $collectionFactory->create(); + $this->meta = $meta; + $this->data = $data; + } + + /** + * @return array + */ + public function getMeta() + { + return $this->meta; + } + + /** + * @param string $fieldSetName + * @param string $fieldName + * @return array + */ + public function getFieldMetaInfo($fieldSetName, $fieldName) + { + return isset($this->meta[$fieldSetName]['fields'][$fieldName]) + ? $this->meta[$fieldSetName]['fields'][$fieldName] + : []; + } + + /** + * Get data + * + * @return array + */ + public function getData() + { + return $this->collection->toArray(); + } + + /** + * Get field name in request + * + * @return string + */ + public function getRequestFieldName() + { + return $this->requestFieldName; + } + + /** + * Get primary field name + * + * @return string + */ + public function getPrimaryFieldName() + { + return $this->primaryFieldName; + } + + /** + * @inheritdoc + */ + public function addFilter($field, $condition = null) + { + $this->collection->addFieldToFilter($field, $condition); + } + + /** + * Add field to select + * + * @param string|array $field + * @param string|null $alias + * @return void + */ + public function addField($field, $alias = null) + { + $this->collection->addFieldToSelect($field, $alias); + } + + /** + * Add ORDER BY to the end or to the beginning + * + * @param string $field + * @param string $direction + * @return void + */ + public function addOrder($field, $direction) + { + $this->collection->addOrder($field, $direction); + } + + /** + * Set Query limit + * + * @param int $offset + * @param int $size + * @return void + */ + public function setLimit($offset, $size) + { + $this->collection->setPageSize($size); + $this->collection->setCurPage($offset); + } + + /** + * Removes field from select + * + * @param string|null $field + * @param bool $isAlias Alias identifier + * @return void + */ + public function removeField($field, $isAlias = false) + { + $this->collection->removeFieldFromSelect($field, $isAlias); + } + + /** + * Removes all fields from select + * + * @return void + */ + public function removeAllFields() + { + $this->collection->removeAllFieldsFromSelect(); + } + + /** + * Retrieve count of loaded items + * + * @return int + */ + public function count() + { + return $this->collection->count(); + } + + /** + * Get config data + * + * @return mixed + */ + public function getConfigData() + { + return isset($this->data['config']) ? $this->data['config'] : []; + } + + /** + * Set data + * + * @param mixed $config + * @return void + */ + public function setConfigData($config) + { + $this->data['config'] = $config; + } + + /** + * @param string $fieldSetName + * @return array + */ + public function getFieldsMetaInfo($fieldSetName) + { + return isset($this->meta[$fieldSetName]['fields']) ? $this->meta[$fieldSetName]['fields'] : []; + } +} diff --git a/app/code/Magento/Cms/Model/Page/DataProvider.php b/app/code/Magento/Cms/Model/Page/DataProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..4797ffbe28c84f086f2a45cb8b084db9ccd2389b --- /dev/null +++ b/app/code/Magento/Cms/Model/Page/DataProvider.php @@ -0,0 +1,228 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Model\Page; + +use Magento\Cms\Model\Resource\Page\Collection; +use Magento\Cms\Model\Resource\Page\CollectionFactory; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; + +/** + * Class DataProvider + */ +class DataProvider implements DataProviderInterface +{ + /** + * @var string + */ + protected $primaryFieldName; + + /** + * @var string + */ + protected $requestFieldName; + + /** + * @var CollectionFactory + */ + protected $collectionFactory; + + /** + * @var Collection + */ + protected $collection; + + /** + * @var array + */ + protected $meta = []; + + /** + * Provider configuration data + * + * @var array + */ + protected $data = []; + + /** + * @param string $primaryFieldName + * @param string $requestFieldName + * @param CollectionFactory $collectionFactory + * @param array $meta + * @param array $data + */ + public function __construct( + $primaryFieldName, + $requestFieldName, + CollectionFactory $collectionFactory, + array $meta = [], + array $data = [] + ) { + $this->primaryFieldName = $primaryFieldName; + $this->requestFieldName = $requestFieldName; + + $this->collection = $collectionFactory->create(); + $this->collection->setFirstStoreFlag(true); + $this->meta = $meta; + $this->data = $data; + } + + /** + * @return array + */ + public function getMeta() + { + return $this->meta; + } + + /** + * Get data + * + * @return array + */ + public function getData() + { + return $this->collection->toArray(); + } + + /** + * @param string $fieldSetName + * @param string $fieldName + * @return array + */ + public function getFieldMetaInfo($fieldSetName, $fieldName) + { + return isset($this->meta[$fieldSetName]['fields'][$fieldName]) + ? $this->meta[$fieldSetName]['fields'][$fieldName] + : []; + } + + /** + * Get field name in request + * + * @return string + */ + public function getRequestFieldName() + { + return $this->requestFieldName; + } + + /** + * Get primary field name + * + * @return string + */ + public function getPrimaryFieldName() + { + return $this->primaryFieldName; + } + + /** + * @inheritdoc + */ + public function addFilter($field, $condition = null) + { + $this->collection->addFieldToFilter($field, $condition); + } + + /** + * Add field to select + * + * @param string|array $field + * @param string|null $alias + * @return void + */ + public function addField($field, $alias = null) + { + $this->collection->addFieldToSelect($field, $alias); + } + + /** + * self::setOrder() alias + * + * @param string $field + * @param string $direction + * @return void + */ + public function addOrder($field, $direction) + { + $this->collection->addOrder($field, $direction); + } + + /** + * Set Query limit + * + * @param int $offset + * @param int $size + * @return void + */ + public function setLimit($offset, $size) + { + $this->collection->setPageSize($size); + $this->collection->setCurPage($offset); + } + + /** + * Removes field from select + * + * @param string|null $field + * @param bool $isAlias Alias identifier + * @return void + */ + public function removeField($field, $isAlias = false) + { + $this->collection->removeFieldFromSelect($field, $isAlias); + } + + /** + * Removes all fields from select + * + * @return void + */ + public function removeAllFields() + { + $this->collection->removeAllFieldsFromSelect(); + } + + /** + * Retrieve count of loaded items + * + * @return int + */ + public function count() + { + return $this->collection->count(); + } + + /** + * Get config data + * + * @return mixed + */ + public function getConfigData() + { + return isset($this->data['config']) ? $this->data['config'] : []; + } + + /** + * Set data + * + * @param mixed $config + * @return void + */ + public function setConfigData($config) + { + $this->data['config'] = $config; + } + + /** + * @param string $fieldSetName + * @return array + */ + public function getFieldsMetaInfo($fieldSetName) + { + return isset($this->meta[$fieldSetName]['fields']) ? $this->meta[$fieldSetName]['fields'] : []; + } +} diff --git a/app/code/Magento/Cms/Ui/DataProvider/Page/Options/IsActive.php b/app/code/Magento/Cms/Model/Page/Source/IsActive.php similarity index 57% rename from app/code/Magento/Cms/Ui/DataProvider/Page/Options/IsActive.php rename to app/code/Magento/Cms/Model/Page/Source/IsActive.php index 4934fc0297f229360d249ee23fe43dda37be7599..7c9d153e5a5a5d8cb363e4830c8e096f82cb92d3 100644 --- a/app/code/Magento/Cms/Ui/DataProvider/Page/Options/IsActive.php +++ b/app/code/Magento/Cms/Model/Page/Source/IsActive.php @@ -3,14 +3,14 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Cms\Ui\DataProvider\Page\Options; +namespace Magento\Cms\Model\Page\Source; -use Magento\Ui\Component\Listing\OptionsInterface; +use Magento\Framework\Data\OptionSourceInterface; /** * Class IsActive */ -class IsActive implements OptionsInterface +class IsActive implements OptionSourceInterface { /** * @var \Magento\Cms\Model\Page @@ -30,19 +30,18 @@ class IsActive implements OptionsInterface /** * Get options * - * @param array $options * @return array */ - public function getOptions(array $options = []) + public function toOptionArray() { - $newOptions = $this->cmsPage->getAvailableStatuses(); - foreach ($newOptions as $key => $value) { - $newOptions[$key] = [ + $options = []; + $availableOptions = $this->cmsPage->getAvailableStatuses(); + foreach ($availableOptions as $key => $value) { + $options[$key] = [ 'label' => $value, 'value' => $key, ]; } - - return array_merge_recursive($newOptions, $options); + return $options; } } diff --git a/app/code/Magento/Cms/Ui/DataProvider/Page/Options/PageLayout.php b/app/code/Magento/Cms/Model/Page/Source/PageLayout.php similarity index 55% rename from app/code/Magento/Cms/Ui/DataProvider/Page/Options/PageLayout.php rename to app/code/Magento/Cms/Model/Page/Source/PageLayout.php index 7a053e0fd3948891f3fa1d10aa5e690d586aecf6..32e8878dbe5b277ea401f09a6098cddeae4eeef8 100644 --- a/app/code/Magento/Cms/Ui/DataProvider/Page/Options/PageLayout.php +++ b/app/code/Magento/Cms/Model/Page/Source/PageLayout.php @@ -3,21 +3,26 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Cms\Ui\DataProvider\Page\Options; +namespace Magento\Cms\Model\Page\Source; +use Magento\Framework\Data\OptionSourceInterface; use Magento\Framework\View\Model\PageLayout\Config\BuilderInterface; -use Magento\Ui\Component\Listing\OptionsInterface; /** * Class PageLayout */ -class PageLayout implements OptionsInterface +class PageLayout implements OptionSourceInterface { /** * @var \Magento\Framework\View\Model\PageLayout\Config\BuilderInterface */ protected $pageLayoutBuilder; + /** + * @var array + */ + protected $options; + /** * Constructor * @@ -31,19 +36,23 @@ class PageLayout implements OptionsInterface /** * Get options * - * @param array $options * @return array */ - public function getOptions(array $options = []) + public function toOptionArray() { - $newOptions = $this->pageLayoutBuilder->getPageLayoutsConfig()->getOptions(); - foreach ($newOptions as $key => $value) { - $newOptions[$key] = [ + if ($this->options !== null) { + return $this->options; + } + $options = []; + $configOptions = $this->pageLayoutBuilder->getPageLayoutsConfig()->getOptions(); + foreach ($configOptions as $key => $value) { + $options[$key] = [ 'label' => $value, 'value' => $key, ]; } + $this->options = $options; - return array_merge_recursive($newOptions, $options); + return $this->options; } } diff --git a/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Widget/ChooserTest.php b/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Widget/ChooserTest.php index 0c075194e3330d099d7bb12b2427b971621f8a81..55761dae44ac94230eb126aa182e22394aaf1d32 100644 --- a/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Widget/ChooserTest.php +++ b/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Block/Widget/ChooserTest.php @@ -35,6 +35,11 @@ class ChooserTest extends \PHPUnit_Framework_TestCase */ protected $urlBuilderMock; + /** + * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + protected $escaper; + /** * @var \Magento\Cms\Model\BlockFactory|\PHPUnit_Framework_MockObject_MockObject */ @@ -66,6 +71,14 @@ class ChooserTest extends \PHPUnit_Framework_TestCase $this->urlBuilderMock = $this->getMockBuilder('Magento\Framework\UrlInterface') ->disableOriginalConstructor() ->getMock(); + $this->escaper = $this->getMockBuilder('Magento\Framework\Escaper') + ->disableOriginalConstructor() + ->setMethods( + [ + 'escapeHtml', + ] + ) + ->getMock(); $this->blockFactoryMock = $this->getMockBuilder('Magento\Cms\Model\BlockFactory') ->setMethods( [ @@ -90,6 +103,7 @@ class ChooserTest extends \PHPUnit_Framework_TestCase [ 'getTitle', 'load', + 'getId', ] ) ->getMock(); @@ -112,15 +126,16 @@ class ChooserTest extends \PHPUnit_Framework_TestCase $this->context = $objectManager->getObject( 'Magento\Backend\Block\Template\Context', [ - 'layout' => $this->layoutMock, + 'layout' => $this->layoutMock, 'mathRandom' => $this->mathRandomMock, - 'urlBuilder' => $this->urlBuilderMock + 'urlBuilder' => $this->urlBuilderMock, + 'escaper' => $this->escaper, ] ); $this->this = $objectManager->getObject( 'Magento\Cms\Block\Adminhtml\Block\Widget\Chooser', [ - 'context' => $this->context, + 'context' => $this->context, 'blockFactory' => $this->blockFactoryMock ] ); @@ -135,13 +150,14 @@ class ChooserTest extends \PHPUnit_Framework_TestCase */ public function testPrepareElementHtml($elementValue, $modelBlockId) { - $elementId = 1; - $uniqId = '126hj4h3j73hk7b347jhkl37gb34'; - $sourceUrl = 'cms/block_widget/chooser/126hj4h3j73hk7b347jhkl37gb34'; - $config = ['key1' => 'value1']; - $fieldsetId = 2; - $html = 'some html'; - $title = 'some title'; + $elementId = 1; + $uniqId = '126hj4h3j73hk7b347jhkl37gb34'; + $sourceUrl = 'cms/block_widget/chooser/126hj4h3j73hk7b347jhkl37gb34'; + $config = ['key1' => 'value1']; + $fieldsetId = 2; + $html = 'some html'; + $title = 'some "><img src=y onerror=prompt(document.domain)>; title'; + $titleEscaped = 'some "><img src=y onerror=prompt(document.domain)>; title'; $this->this->setConfig($config); $this->this->setFieldsetId($fieldsetId); @@ -197,13 +213,18 @@ class ChooserTest extends \PHPUnit_Framework_TestCase $this->modelBlockMock->expects($this->any()) ->method('getTitle') ->willReturn($title); - $this->chooserMock->expects($this->any()) - ->method('setLabel') - ->with($title) - ->willReturnSelf(); $this->chooserMock->expects($this->atLeastOnce()) ->method('toHtml') ->willReturn($html); + if (!empty($elementValue) && !empty($modelBlockId)) { + $this->escaper->expects(($this->atLeastOnce())) + ->method('escapeHtml') + ->willReturn($titleEscaped); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('setLabel') + ->with($titleEscaped) + ->willReturnSelf(); + } $this->elementMock->expects($this->atLeastOnce()) ->method('setData') ->with('after_element_html', $html) diff --git a/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Page/Widget/ChooserTest.php b/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Page/Widget/ChooserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..75107bcb42de11db287607e49595aa6fecfd637b --- /dev/null +++ b/app/code/Magento/Cms/Test/Unit/Block/Adminhtml/Page/Widget/ChooserTest.php @@ -0,0 +1,271 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Test\Unit\Block\Adminhtml\Page\Widget; + +/** + * @covers \Magento\Cms\Block\Adminhtml\Page\Widget\Chooser + */ +class ChooserTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Cms\Block\Adminhtml\Page\Widget\Chooser + */ + protected $this; + + /** + * @var \Magento\Backend\Block\Template\Context + */ + protected $context; + + /** + * @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject + */ + protected $mathRandomMock; + + /** + * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $urlBuilderMock; + + /** + * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + protected $escaper; + + /** + * @var \Magento\Cms\Model\Page|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cmsPageMock; + + /** + * @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutMock; + + /** + * @var \Magento\Cms\Model\PageFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $pageFactoryMock; + + /** + * @var \Magento\Framework\Data\Form\Element\AbstractElement|\PHPUnit_Framework_MockObject_MockObject + */ + protected $elementMock; + + /** + * @var \Magento\Framework\View\Element\BlockInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $chooserMock; + + protected function setUp() + { + $this->layoutMock = $this->getMockBuilder('Magento\Framework\View\LayoutInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->mathRandomMock = $this->getMockBuilder('Magento\Framework\Math\Random') + ->disableOriginalConstructor() + ->getMock(); + $this->urlBuilderMock = $this->getMockBuilder('Magento\Framework\UrlInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->escaper = $this->getMockBuilder('Magento\Framework\Escaper') + ->disableOriginalConstructor() + ->setMethods( + [ + 'escapeHtml', + ] + ) + ->getMock(); + $this->pageFactoryMock = $this->getMockBuilder('Magento\Cms\Model\PageFactory') + ->setMethods( + [ + 'create', + ] + ) + ->disableOriginalConstructor() + ->getMock(); + $this->elementMock = $this->getMockBuilder('Magento\Framework\Data\Form\Element\AbstractElement') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getId', + 'getValue', + 'setData', + ] + ) + ->getMock(); + $this->cmsPageMock = $this->getMockBuilder('Magento\Cms\Model\Page') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getTitle', + 'load', + 'getId', + ] + ) + ->getMock(); + $this->chooserMock = $this->getMockBuilder('Magento\Framework\View\Element\BlockInterface') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setElement', + 'setConfig', + 'setFieldsetId', + 'setSourceUrl', + 'setUniqId', + 'setLabel', + 'toHtml', + ] + ) + ->getMock(); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->context = $objectManager->getObject( + 'Magento\Backend\Block\Template\Context', + [ + 'layout' => $this->layoutMock, + 'mathRandom' => $this->mathRandomMock, + 'urlBuilder' => $this->urlBuilderMock, + 'escaper' => $this->escaper, + ] + ); + $this->this = $objectManager->getObject( + 'Magento\Cms\Block\Adminhtml\Page\Widget\Chooser', + [ + 'context' => $this->context, + 'pageFactory' => $this->pageFactoryMock + ] + ); + } + + /** + * @covers \Magento\Cms\Block\Adminhtml\Block\Widget\Chooser::prepareElementHtml + * + * @param string $elementValue + * @param integer|null $cmsPageId + * + * @dataProvider prepareElementHtmlDataProvider + */ + public function testPrepareElementHtml($elementValue, $cmsPageId) + { + //$elementValue = 12345; + //$cmsPageId = 1; + $elementId = 1; + $uniqId = '126hj4h3j73hk7b347jhkl37gb34'; + $sourceUrl = 'cms/page_widget/chooser/126hj4h3j73hk7b347jhkl37gb34'; + $config = ['key1' => 'value1']; + $fieldsetId = 2; + $html = 'some html'; + $title = 'some "><img src=y onerror=prompt(document.domain)>; title'; + $titleEscaped = 'some "><img src=y onerror=prompt(document.domain)>; title'; + + $this->this->setConfig($config); + $this->this->setFieldsetId($fieldsetId); + + $this->elementMock->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn($elementId); + $this->mathRandomMock->expects($this->atLeastOnce()) + ->method('getUniqueHash') + ->with($elementId) + ->willReturn($uniqId); + $this->urlBuilderMock->expects($this->atLeastOnce()) + ->method('getUrl') + ->with('cms/page_widget/chooser', ['uniq_id' => $uniqId]) + ->willReturn($sourceUrl); + $this->layoutMock->expects($this->atLeastOnce()) + ->method('createBlock') + ->with('Magento\Widget\Block\Adminhtml\Widget\Chooser') + ->willReturn($this->chooserMock); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('setElement') + ->with($this->elementMock) + ->willReturnSelf(); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('setConfig') + ->with($config) + ->willReturnSelf(); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('setFieldsetId') + ->with($fieldsetId) + ->willReturnSelf(); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('setSourceUrl') + ->with($sourceUrl) + ->willReturnSelf(); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('setUniqId') + ->with($uniqId) + ->willReturnSelf(); + $this->elementMock->expects($this->atLeastOnce()) + ->method('getValue') + ->willReturn($elementValue); + $this->pageFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->cmsPageMock); + $this->cmsPageMock->expects($this->any()) + ->method('load') + ->with((int)$elementValue) + ->willReturnSelf(); + $this->cmsPageMock->expects($this->any()) + ->method('getId') + ->willReturn($cmsPageId); + $this->cmsPageMock->expects($this->any()) + ->method('getTitle') + ->willReturn($title); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('toHtml') + ->willReturn($html); + if (!empty($elementValue) && !empty($cmsPageId)) { + $this->escaper->expects(($this->atLeastOnce())) + ->method('escapeHtml') + ->willReturn($titleEscaped); + $this->chooserMock->expects($this->atLeastOnce()) + ->method('setLabel') + ->with($titleEscaped) + ->willReturnSelf(); + } + $this->elementMock->expects($this->atLeastOnce()) + ->method('setData') + ->with('after_element_html', $html) + ->willReturnSelf(); + + $this->assertEquals($this->elementMock, $this->this->prepareElementHtml($this->elementMock)); + } + + public function prepareElementHtmlDataProvider() + { + return [ + 'elementValue NOT EMPTY, modelBlockId NOT EMPTY' => [ + 'elementValue' => 'some value', + 'cmsPageId' => 1, + ], + 'elementValue NOT EMPTY, modelBlockId IS EMPTY' => [ + 'elementValue' => 'some value', + 'cmsPageId' => null, + ], + 'elementValue IS EMPTY, modelBlockId NEVER REACHED' => [ + 'elementValue' => '', + 'cmsPageId' => 1, + ] + ]; + } + + /** + * @covers \Magento\Cms\Block\Adminhtml\Page\Widget\Chooser::getGridUrl + */ + public function testGetGridUrl() + { + $url = 'some url'; + + $this->urlBuilderMock->expects($this->atLeastOnce()) + ->method('getUrl') + ->with('cms/page_widget/chooser', ['_current' => true]) + ->willReturn($url); + + $this->assertEquals($url, $this->this->getGridUrl()); + } +} diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php new file mode 100644 index 0000000000000000000000000000000000000000..ecdf19a805f4cda93e6528a07b47cde1c2b97e14 --- /dev/null +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Ui\Component\Listing\Column; + +use Magento\Framework\UrlInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Ui\Component\Listing\Columns\Column; + +/** + * Class BlockActions + */ +class BlockActions extends Column +{ + /** + * Url path + */ + const URL_PATH = 'cms/block/edit'; + + /** + * @var UrlInterface + */ + protected $urlBuilder; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param UrlInterface $urlBuilder + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + UrlInterface $urlBuilder, + array $components = [], + array $data = [] + ) { + $this->urlBuilder = $urlBuilder; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + foreach ($items as & $item) { + if (isset($item['block_id'])) { + $item[$this->getData('name')] = [ + 'edit' => [ + 'href' => $this->urlBuilder->getUrl(static::URL_PATH, ['block_id' => $item['block_id']]), + 'label' => __('Edit'), + ] + ]; + } + } + return $items; + } +} diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php new file mode 100644 index 0000000000000000000000000000000000000000..2a8140c0923cf2ac52304dc6ad67f8a2240e773a --- /dev/null +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Ui\Component\Listing\Column; + +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Ui\Component\Listing\Columns\Column; +use Magento\Cms\Block\Adminhtml\Page\Grid\Renderer\Action\UrlBuilder; +use Magento\Framework\UrlInterface; + +/** + * Class PageActions + */ +class PageActions extends Column +{ + /** + * Url path + */ + const URL_PATH = 'cms/page/edit'; + + /** + * @var UrlBuilder + */ + protected $actionUrlBuilder; + + /** + * @var UrlInterface + */ + protected $urlBuilder; + + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param UrlBuilder $actionUrlBuilder + * @param UrlInterface $urlBuilder + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + UrlBuilder $actionUrlBuilder, + UrlInterface $urlBuilder, + array $components = [], + array $data = [] + ) { + $this->urlBuilder = $urlBuilder; + $this->actionUrlBuilder = $actionUrlBuilder; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + foreach ($items as & $item) { + if (isset($item['page_id'])) { + $item[$this->getData('name')]['edit'] = [ + 'href' => $this->urlBuilder->getUrl(static::URL_PATH, ['page_id' => $item['page_id']]), + 'label' => __('Edit'), + 'hidden' => true + ]; + } + if (isset($item['identifier'])) { + $item[$this->getData('name')]['preview'] = [ + 'href' => $this->actionUrlBuilder->getUrl( + $item['identifier'], + isset($item['_first_store_id']) ? $item['_first_store_id'] : null, + isset($item['store_code']) ? $item['store_code'] : null + ), + 'label' => __('Preview') + ]; + } + } + + return $items; + } +} diff --git a/app/code/Magento/Cms/composer.json b/app/code/Magento/Cms/composer.json index 9ee9de410e132ace5520da29bfb9f6edc89fb4c7..9b0c037e3e12103a5985b9972867b36512e3c63c 100644 --- a/app/code/Magento/Cms/composer.json +++ b/app/code/Magento/Cms/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-email": "0.74.0-beta6", - "magento/module-ui": "0.74.0-beta6", - "magento/module-variable": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-email": "0.74.0-beta7", + "magento/module-ui": "0.74.0-beta7", + "magento/module-variable": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml index 2e9d8a6ea0b25b06093db7dfb319d280866d1fac..dbdf185d5083e02bd98847af6d282fc1f0de91b3 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml @@ -8,7 +8,8 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> - <ui_component name="cms_block_listing" component="listing"/> + <uiComponent name="cms_block_listing"/> </referenceContainer> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> </body> </page> diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml index 6f1975adb97cd11e5032ed1b455183ac0a653f31..22788b865327bc82bdaa19f196bcbb469bdaeea1 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml @@ -92,14 +92,6 @@ </item> </item> </argument> - <argument name="row_data_provider" xsi:type="array"> - <item name="actions" xsi:type="array"> - <item name="class" xsi:type="string">Magento\Cms\Ui\DataProvider\Block\Row\Actions</item> - </item> - <item name="store_id" xsi:type="array"> - <item name="class" xsi:type="string">Magento\Store\Ui\DataProvider\Row</item> - </item> - </argument> </arguments> </referenceBlock> <referenceBlock name="sorting"> diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml index a63fe9f63f08d305c5595171900176096473e033..b5fbe5373d4f837ce76412ae4d417d182eae26d9 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml @@ -6,9 +6,10 @@ */ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <update handle="styles"/> <body> <referenceContainer name="content"> - <ui_component name="cms_page_listing" component="listing"/> + <uiComponent name="cms_page_listing"/> </referenceContainer> </body> </page> diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml index bebf23cacd86b98d4f7e4f6c3af734c4cba77515..55a8f042883487aa8d6e88524a7e6cbf1ebe6bf6 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml @@ -89,14 +89,6 @@ </item> </item> </argument> - <argument name="row_data_provider" xsi:type="array"> - <item name="actions" xsi:type="array"> - <item name="class" xsi:type="string">Magento\Cms\Ui\DataProvider\Page\Row\Actions</item> - </item> - <item name="store_id" xsi:type="array"> - <item name="class" xsi:type="string">Magento\Store\Ui\DataProvider\Row</item> - </item> - </argument> </arguments> </referenceBlock> <referenceBlock name="massactions"> diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml new file mode 100644 index 0000000000000000000000000000000000000000..da8c5b01d5ea6cd2ff079669e6404ab400fa8dad --- /dev/null +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml @@ -0,0 +1,383 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Ui/etc/ui_configuration.xsd"> + <argument name="context" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Framework\View\Element\UiComponent\Context</argument> + <argument name="namespace" xsi:type="string">cms_block_listing</argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="provider" xsi:type="string">cms_block_listing.cms_block_listing_data_source</item> + </item> + <item name="deps" xsi:type="string">cms_block_listing.cms_block_listing_data_source</item> + </item> + <item name="spinner" xsi:type="string">cms_block_columns</item> + <item name="buttons" xsi:type="array"> + <item name="add" xsi:type="array"> + <item name="name" xsi:type="string">add</item> + <item name="label" xsi:type="string" translate="true">Add New Block</item> + <item name="class" xsi:type="string">primary</item> + <item name="url" xsi:type="string">*/*/new</item> + </item> + </item> + </argument> + <container name="listing_top"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">ui/grid/toolbar</item> + </item> + </argument> + <container name="default_view"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/view</item> + <item name="displayArea" xsi:type="string">dataGridActions</item> + </item> + </argument> + </container> + <container name="columns_controls"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item> + <item name="displayArea" xsi:type="string">dataGridActions</item> + </item> + </argument> + </container> + <filters name="listing_filters"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">dataGridFilters</item> + <item name="dataScope" xsi:type="string">params.filters</item> + </item> + </argument> + <filterRange name="block_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">block_id</item> + <item name="label" xsi:type="string" translate="true">ID</item> + </item> + </argument> + <filterInput name="from"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">from</item> + <item name="label" xsi:type="string" translate="true">from</item> + <item name="placeholder" xsi:type="string" translate="true">From</item> + </item> + </argument> + </filterInput> + <filterInput name="to"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">to</item> + <item name="label" xsi:type="string" translate="true">to</item> + <item name="placeholder" xsi:type="string" translate="true">To</item> + </item> + </argument> + </filterInput> + </filterRange> + <filterInput name="title"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">title</item> + <item name="label" xsi:type="string" translate="true">Title</item> + </item> + </argument> + </filterInput> + <filterInput name="identifier"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">identifier</item> + <item name="label" xsi:type="string" translate="true">Identifier</item> + </item> + </argument> + </filterInput> + <filterSelect name="store_id"> + <argument name="optionsProvider" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Store\Ui\Component\Listing\Column\Store\Options</argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="caption" xsi:type="string" translate="true">Select...</item> + <item name="dataScope" xsi:type="string">store_id</item> + <item name="label" xsi:type="string" translate="true">Store View</item> + </item> + </argument> + </filterSelect> + <filterSelect name="is_active"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="caption" xsi:type="string" translate="true">Select...</item> + <item name="label" xsi:type="string" translate="true">Status</item> + <item name="dataScope" xsi:type="string">is_active</item> + <item name="options" xsi:type="array"> + <item name="disable" xsi:type="array"> + <item name="value" xsi:type="string">0</item> + <item name="label" xsi:type="string" translate="true">Disabled</item> + </item> + <item name="enable" xsi:type="array"> + <item name="value" xsi:type="string">1</item> + <item name="label" xsi:type="string" translate="true">Enabled</item> + </item> + </item> + </item> + </argument> + </filterSelect> + <filterRange name="creation_time" class="Magento\Ui\Component\Filters\Type\DateRange"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">creation_time</item> + <item name="label" xsi:type="string" translate="true">Created</item> + </item> + </argument> + <filterDate name="from"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">from</item> + <item name="label" xsi:type="string" translate="true">From</item> + <item name="placeholder" xsi:type="string" translate="true">From</item> + </item> + </argument> + </filterDate> + <filterDate name="to"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">to</item> + <item name="label" xsi:type="string" translate="true">To</item> + <item name="placeholder" xsi:type="string" translate="true">To</item> + </item> + </argument> + </filterDate> + </filterRange> + <filterRange name="update_time" class="Magento\Ui\Component\Filters\Type\DateRange"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">update_time</item> + <item name="label" xsi:type="string" translate="true">Modified</item> + </item> + </argument> + <filterDate name="from"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">from</item> + <item name="label" xsi:type="string" translate="true">From</item> + <item name="placeholder" xsi:type="string" translate="true">From</item> + </item> + </argument> + </filterDate> + <filterDate name="to"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">to</item> + <item name="label" xsi:type="string" translate="true">To</item> + <item name="placeholder" xsi:type="string" translate="true">To</item> + </item> + </argument> + </filterDate> + </filterRange> + </filters> + <massaction name="listing_massaction"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">bottom</item> + <item name="actions" xsi:type="array"> + <item name="delete" xsi:type="array"> + <item name="confirm" xsi:type="string" translate="true">Are you sure you want to perform this action?</item> + <item name="type" xsi:type="string">delete</item> + <item name="label" xsi:type="string" translate="true">Delete</item> + <item name="url" xsi:type="string">cms/block/massDelete</item> + </item> + </item> + <item name="indexField" xsi:type="string">block_id</item> + </item> + </argument> + </massaction> + <paging name="listing_paging"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">bottom</item> + <item name="options" xsi:type="array"> + <item name="20" xsi:type="array"> + <item name="value" xsi:type="number">20</item> + <item name="label" xsi:type="string" translate="true">20</item> + </item> + <item name="30" xsi:type="array"> + <item name="value" xsi:type="number">30</item> + <item name="label" xsi:type="string" translate="true">30</item> + </item> + <item name="50" xsi:type="array"> + <item name="value" xsi:type="number">50</item> + <item name="label" xsi:type="string" translate="true">50</item> + </item> + <item name="100" xsi:type="array"> + <item name="value" xsi:type="number">100</item> + <item name="label" xsi:type="string" translate="true">100</item> + </item> + <item name="200" xsi:type="array"> + <item name="value" xsi:type="number">200</item> + <item name="label" xsi:type="string" translate="true">200</item> + </item> + </item> + </item> + </argument> + </paging> + </container> + <dataSource name="cms_block_listing_data_source"> + <argument name="dataProvider" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Cms\Model\Block\DataProvider</argument> + <argument name="primaryFieldName" xsi:type="string">block_id</argument> + <argument name="requestFieldName" xsi:type="string">id</argument> + <argument name="meta" xsi:type="array"> + <item name="cms_page" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">CMS Page</item> + </item> + </item> + </argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> + </item> + <item name="config" xsi:type="array"> + <item name="update_url" xsi:type="string">mui/index/render</item> + </item> + </argument> + </dataSource> + <columns name="cms_block_columns"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="childDefaults" xsi:type="array"> + <item name="actionField" xsi:type="string">actions</item> + <item name="clickAction" xsi:type="string">edit</item> + <item name="appendTo" xsi:type="string">cms_block_listing.cms_block_listing.listing_top.columns_controls</item> + </item> + </item> + </argument> + <column name="ids" class="Magento\Ui\Component\MassAction\Columns\Column"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/multiselect</item> + </item> + <item name="config" xsi:type="array"> + <item name="indexField" xsi:type="string">block_id</item> + <item name="appendTo" xsi:type="boolean">false</item> + </item> + </argument> + </column> + <column name="block_id"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="sorting" xsi:type="string">asc</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">ID</item> + </item> + </argument> + </column> + <column name="title"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Title</item> + </item> + </argument> + </column> + <column name="identifier"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Identifier</item> + </item> + </argument> + </column> + <column name="store_id" class="Magento\Store\Ui\Component\Listing\Column\Store"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> + </item> + <item name="config" xsi:type="array"> + <item name="sortable" xsi:type="boolean">false</item> + <item name="dataType" xsi:type="string">text</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Store View</item> + </item> + </argument> + </column> + <column name="is_active"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> + </item> + <item name="options" xsi:type="array"> + <item name="disable" xsi:type="array"> + <item name="value" xsi:type="string">0</item> + <item name="label" xsi:type="string" translate="true">Disabled</item> + </item> + <item name="enable" xsi:type="array"> + <item name="value" xsi:type="string">1</item> + <item name="label" xsi:type="string" translate="true">Enabled</item> + </item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">select</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Status</item> + </item> + </argument> + </column> + <column name="creation_time"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">date</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Created</item> + </item> + </argument> + </column> + <column name="update_time"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">date</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Modified</item> + </item> + </argument> + </column> + <column name="actions" class="Magento\Cms\Ui\Component\Listing\Column\BlockActions"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">actions</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Action</item> + <item name="data_type" xsi:type="string">actions</item> + <item name="filterable" xsi:type="boolean">false</item> + <item name="sortable" xsi:type="boolean">false</item> + </item> + </argument> + </column> + </columns> +</listing> diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml new file mode 100644 index 0000000000000000000000000000000000000000..3e67e0ef1235c458b18a948d2a369db408b1a698 --- /dev/null +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml @@ -0,0 +1,399 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Ui/etc/ui_configuration.xsd"> + <argument name="context" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Framework\View\Element\UiComponent\Context</argument> + <argument name="namespace" xsi:type="string">cms_page_listing</argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="provider" xsi:type="string">cms_page_listing.cms_page_listing_data_source</item> + </item> + <item name="deps" xsi:type="string">cms_page_listing.cms_page_listing_data_source</item> + </item> + <item name="spinner" xsi:type="string">cms_page_columns</item> + <item name="buttons" xsi:type="array"> + <item name="add" xsi:type="array"> + <item name="name" xsi:type="string">add</item> + <item name="label" xsi:type="string" translate="true">Add New Page</item> + <item name="class" xsi:type="string">primary</item> + <item name="url" xsi:type="string">*/*/new</item> + </item> + </item> + </argument> + <dataSource name="cms_page_listing_data_source"> + <argument name="dataProvider" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Cms\Model\Page\DataProvider</argument> + <argument name="primaryFieldName" xsi:type="string">block_id</argument> + <argument name="requestFieldName" xsi:type="string">id</argument> + <argument name="meta" xsi:type="array"> + <item name="cms_block" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">CMS Block</item> + </item> + </item> + </argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> + </item> + <item name="config" xsi:type="array"> + <item name="update_url" xsi:type="string">mui/index/render</item> + </item> + </argument> + </dataSource> + <container name="listing_top"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">ui/grid/toolbar</item> + </item> + </argument> + <container name="default_view"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/view</item> + <item name="displayArea" xsi:type="string">dataGridActions</item> + </item> + </argument> + </container> + <container name="columns_controls"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item> + <item name="displayArea" xsi:type="string">dataGridActions</item> + </item> + </argument> + </container> + <filters name="listing_filters"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">dataGridFilters</item> + <item name="dataScope" xsi:type="string">params.filters</item> + </item> + </argument> + <filterRange name="page_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">page_id</item> + <item name="label" xsi:type="string" translate="true">ID</item> + </item> + </argument> + <filterInput name="from"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">from</item> + <item name="label" xsi:type="string" translate="true">from</item> + <item name="placeholder" xsi:type="string" translate="true">From</item> + </item> + </argument> + </filterInput> + <filterInput name="to"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">to</item> + <item name="label" xsi:type="string" translate="true">to</item> + <item name="placeholder" xsi:type="string" translate="true">To</item> + </item> + </argument> + </filterInput> + </filterRange> + <filterInput name="title"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">title</item> + <item name="label" xsi:type="string" translate="true">Title</item> + </item> + </argument> + </filterInput> + <filterInput name="identifier"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">identifier</item> + <item name="label" xsi:type="string" translate="true">URL Key</item> + </item> + </argument> + </filterInput> + <filterSelect name="page_layout"> + <argument name="optionsProvider" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Cms\Model\Page\Source\PageLayout</argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">page_layout</item> + <item name="label" xsi:type="string" translate="true">Layout</item> + <item name="caption" xsi:type="string" translate="true">Select...</item> + </item> + </argument> + </filterSelect> + <filterSelect name="store_id"> + <argument name="optionsProvider" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Store\Ui\Component\Listing\Column\Store\Options</argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">store_id</item> + <item name="caption" xsi:type="string" translate="true">Select...</item> + <item name="label" xsi:type="string" translate="true">Store View</item> + </item> + </argument> + </filterSelect> + <filterSelect name="is_active"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">is_active</item> + <item name="label" xsi:type="string" translate="true">Status</item> + <item name="caption" xsi:type="string" translate="true">Select...</item> + <item name="options" xsi:type="array"> + <item name="disable" xsi:type="array"> + <item name="value" xsi:type="string">0</item> + <item name="label" xsi:type="string" translate="true">Disabled</item> + </item> + <item name="enable" xsi:type="array"> + <item name="value" xsi:type="string">1</item> + <item name="label" xsi:type="string" translate="true">Enabled</item> + </item> + </item> + </item> + </argument> + </filterSelect> + <filterRange name="creation_time" class="Magento\Ui\Component\Filters\Type\DateRange"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">creation_time</item> + <item name="label" xsi:type="string" translate="true">Created</item> + </item> + </argument> + <filterDate name="from"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">from</item> + <item name="label" xsi:type="string" translate="true">from</item> + <item name="placeholder" xsi:type="string" translate="true">From</item> + </item> + </argument> + </filterDate> + <filterDate name="to"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">to</item> + <item name="label" xsi:type="string" translate="true">to</item> + <item name="placeholder" xsi:type="string" translate="true">To</item> + </item> + </argument> + </filterDate> + </filterRange> + <filterRange name="update_time" class="Magento\Ui\Component\Filters\Type\DateRange"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">update_time</item> + <item name="label" xsi:type="string" translate="true">Modified</item> + </item> + </argument> + <filterDate name="from"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">from</item> + <item name="label" xsi:type="string" translate="true">from</item> + <item name="placeholder" xsi:type="string" translate="true">From</item> + </item> + </argument> + </filterDate> + <filterDate name="to"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">to</item> + <item name="label" xsi:type="string" translate="true">to</item> + <item name="placeholder" xsi:type="string" translate="true">To</item> + </item> + </argument> + </filterDate> + </filterRange> + </filters> + <massaction name="listing_massaction"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">bottom</item> + <item name="actions" xsi:type="array"> + <item name="delete" xsi:type="array"> + <item name="confirm" xsi:type="string" translate="true">Delete selected items?</item> + <item name="type" xsi:type="string">delete</item> + <item name="label" xsi:type="string" translate="true">Delete</item> + <item name="url" xsi:type="string">cms/page/massDelete</item> + </item> + </item> + <item name="indexField" xsi:type="string">page_id</item> + </item> + </argument> + </massaction> + <paging name="listing_paging"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">bottom</item> + <item name="options" xsi:type="array"> + <item name="20" xsi:type="array"> + <item name="value" xsi:type="number">20</item> + <item name="label" xsi:type="string" translate="true">20</item> + </item> + <item name="30" xsi:type="array"> + <item name="value" xsi:type="number">30</item> + <item name="label" xsi:type="string" translate="true">30</item> + </item> + <item name="50" xsi:type="array"> + <item name="value" xsi:type="number">50</item> + <item name="label" xsi:type="string" translate="true">50</item> + </item> + <item name="100" xsi:type="array"> + <item name="value" xsi:type="number">100</item> + <item name="label" xsi:type="string" translate="true">100</item> + </item> + <item name="200" xsi:type="array"> + <item name="value" xsi:type="number">200</item> + <item name="label" xsi:type="string" translate="true">200</item> + </item> + </item> + </item> + </argument> + </paging> + </container> + <columns name="cms_page_columns"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="childDefaults" xsi:type="array"> + <item name="actionField" xsi:type="string">actions</item> + <item name="clickAction" xsi:type="string">edit</item> + <item name="appendTo" xsi:type="string">cms_page_listing.cms_page_listing.listing_top.columns_controls</item> + </item> + </item> + </argument> + <column name="ids" class="Magento\Ui\Component\MassAction\Columns\Column"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/multiselect</item> + </item> + <item name="config" xsi:type="array"> + <item name="indexField" xsi:type="string">page_id</item> + <item name="appendTo" xsi:type="string"></item> + </item> + </argument> + </column> + <column name="page_id"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="sorting" xsi:type="string">asc</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">ID</item> + </item> + </argument> + </column> + <column name="title"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Title</item> + </item> + </argument> + </column> + <column name="identifier"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">URL Key</item> + </item> + </argument> + </column> + <column name="page_layout"> + <argument name="data" xsi:type="array"> + <item name="options" xsi:type="object">Magento\Cms\Model\Page\Source\PageLayout</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">select</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Layout</item> + </item> + </argument> + </column> + <column name="store_id" class="Magento\Store\Ui\Component\Listing\Column\Store"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> + </item> + <item name="config" xsi:type="array"> + <item name="sortable" xsi:type="boolean">false</item> + <item name="dataType" xsi:type="string">text</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Store View</item> + </item> + </argument> + </column> + <column name="is_active"> + <argument name="data" xsi:type="array"> + <item name="options" xsi:type="object">Magento\Cms\Model\Page\Source\IsActive</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">select</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Status</item> + </item> + </argument> + </column> + <column name="creation_time"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">date</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Created</item> + </item> + </argument> + </column> + <column name="update_time"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">date</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Modified</item> + </item> + </argument> + </column> + <column name="actions" class="Magento\Cms\Ui\Component\Listing\Column\PageActions"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">actions</item> + <item name="align" xsi:type="string">left</item> + <item name="label" xsi:type="string" translate="true">Action</item> + <item name="data_type" xsi:type="string">actions</item> + <item name="filterable" xsi:type="boolean">false</item> + <item name="sortable" xsi:type="boolean">false</item> + </item> + </argument> + </column> + </columns> +</listing> diff --git a/app/code/Magento/CmsUrlRewrite/composer.json b/app/code/Magento/CmsUrlRewrite/composer.json index 06f0e19df1fb840dd3dde3e6028ab68dda347b3a..6723b56a38eefe51d91034c726c045e014d25550 100644 --- a/app/code/Magento/CmsUrlRewrite/composer.json +++ b/app/code/Magento/CmsUrlRewrite/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-url-rewrite": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-url-rewrite": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Config/Model/Config/Backend/File.php b/app/code/Magento/Config/Model/Config/Backend/File.php index e7a119f79af9f0bf78d8f459ff0d30875abd097b..a08ed7d4f23894640e6592728f9a2c6a8eb1432b 100644 --- a/app/code/Magento/Config/Model/Config/Backend/File.php +++ b/app/code/Magento/Config/Model/Config/Backend/File.php @@ -5,6 +5,7 @@ */ namespace Magento\Config\Model\Config\Backend; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; @@ -196,7 +197,7 @@ class File extends \Magento\Framework\App\Config\Value protected function _prependScopeInfo($path) { $scopeInfo = $this->getScope(); - if (\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT != $this->getScope()) { + if (ScopeConfigInterface::SCOPE_TYPE_DEFAULT != $this->getScope()) { $scopeInfo .= '/' . $this->getScopeId(); } return $scopeInfo . '/' . $path; @@ -213,7 +214,7 @@ class File extends \Magento\Framework\App\Config\Value protected function _appendScopeInfo($path) { $path .= '/' . $this->getScope(); - if (\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT != $this->getScope()) { + if (ScopeConfigInterface::SCOPE_TYPE_DEFAULT != $this->getScope()) { $path .= '/' . $this->getScopeId(); } return $path; diff --git a/app/code/Magento/Config/Model/Config/Backend/Locale.php b/app/code/Magento/Config/Model/Config/Backend/Locale.php index 0881afdebfc3839d52d0c27de0052ae6a8bd68b1..3d057fd6df864d23061ba4d1d762e265482eb595 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Locale.php +++ b/app/code/Magento/Config/Model/Config/Backend/Locale.php @@ -9,6 +9,8 @@ */ namespace Magento\Config\Model\Config\Backend; +use Magento\Framework\App\Config\ScopeConfigInterface; + class Locale extends \Magento\Framework\App\Config\Value { /** @@ -91,7 +93,7 @@ class Locale extends \Magento\Framework\App\Config\Value } switch ($data->getScope()) { - case \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT: + case ScopeConfigInterface::SCOPE_TYPE_DEFAULT: $scopeName = __('Default scope'); break; diff --git a/app/code/Magento/Config/Model/Config/ScopeDefiner.php b/app/code/Magento/Config/Model/Config/ScopeDefiner.php index 893496d874009b9834fc2f1821057283ba01e323..f69e9dd96d2eb820a87a9d1f5905445df9c576df 100644 --- a/app/code/Magento/Config/Model/Config/ScopeDefiner.php +++ b/app/code/Magento/Config/Model/Config/ScopeDefiner.php @@ -5,6 +5,7 @@ */ namespace Magento\Config\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\ScopeInterface as StoreScopeInterface; /** @@ -38,6 +39,6 @@ class ScopeDefiner 'store' ) ? StoreScopeInterface::SCOPE_STORE : ($this->_request->getParam( 'website' - ) ? StoreScopeInterface::SCOPE_WEBSITE : \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT); + ) ? StoreScopeInterface::SCOPE_WEBSITE : ScopeConfigInterface::SCOPE_TYPE_DEFAULT); } } diff --git a/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php b/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php index e10a1a1c3e725333743bea341d6170865f17d119..03ed66f29abec3ebd79735f648aefcd633dc44cc 100644 --- a/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php +++ b/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php @@ -5,6 +5,7 @@ */ namespace Magento\Config\Model\Config\Structure; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\StoreManagerInterface; abstract class AbstractElement implements ElementInterface @@ -136,7 +137,7 @@ abstract class AbstractElement implements ElementInterface $showInScope = [ \Magento\Store\Model\ScopeInterface::SCOPE_STORE => $this->_hasVisibilityValue('showInStore'), \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE => $this->_hasVisibilityValue('showInWebsite'), - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT => $this->_hasVisibilityValue('showInDefault'), + ScopeConfigInterface::SCOPE_TYPE_DEFAULT => $this->_hasVisibilityValue('showInDefault'), ]; if ($this->_storeManager->isSingleStoreMode()) { diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/ScopeDefinerTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/ScopeDefinerTest.php index 23069beec258fa8c6ab4e398c537a4874a9010b7..e0c64a35053ad44c88baa18861e84641a995d17d 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/ScopeDefinerTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/ScopeDefinerTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Config\Test\Unit\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class ScopeDefinerTest extends \PHPUnit_Framework_TestCase @@ -31,7 +32,7 @@ class ScopeDefinerTest extends \PHPUnit_Framework_TestCase public function testGetScopeReturnsDefaultScopeIfNoScopeDataIsSpecified() { - $this->assertEquals(\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $this->_model->getScope()); + $this->assertEquals(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $this->_model->getScope()); } public function testGetScopeReturnsStoreScopeIfStoreIsSpecified() diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Structure/AbstractElementTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Structure/AbstractElementTest.php index 03e9fd8d2266e5c9256c74a81716e59e4eb40ac0..778141ab2132096aa8d0e750f7175bebdcea935b 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/Structure/AbstractElementTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Structure/AbstractElementTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Config\Test\Unit\Model\Config\Structure; +use Magento\Framework\App\Config\ScopeConfigInterface; + class AbstractElementTest extends \PHPUnit_Framework_TestCase { /** @@ -77,7 +79,7 @@ class AbstractElementTest extends \PHPUnit_Framework_TestCase $this->_storeManager->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); $this->_model->setData( ['showInDefault' => 1, 'showInStore' => 0, 'showInWebsite' => 0], - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ); $this->assertTrue($this->_model->isVisible()); } @@ -87,7 +89,7 @@ class AbstractElementTest extends \PHPUnit_Framework_TestCase $this->_storeManager->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); $this->_model->setData( ['hide_in_single_store_mode' => 1, 'showInDefault' => 1, 'showInStore' => 0, 'showInWebsite' => 0], - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ); $this->assertFalse($this->_model->isVisible()); } @@ -100,7 +102,7 @@ class AbstractElementTest extends \PHPUnit_Framework_TestCase $this->_storeManager->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); $this->_model->setData( ['showInDefault' => 0, 'showInStore' => 0, 'showInWebsite' => 0], - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ); $this->assertFalse($this->_model->isVisible()); } @@ -121,7 +123,7 @@ class AbstractElementTest extends \PHPUnit_Framework_TestCase return [ [ ['showInDefault' => 1, 'showInStore' => 0, 'showInWebsite' => 0], - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, ], [ ['showInDefault' => 0, 'showInStore' => 1, 'showInWebsite' => 0], @@ -150,7 +152,7 @@ class AbstractElementTest extends \PHPUnit_Framework_TestCase return [ [ ['showInDefault' => 0, 'showInStore' => 1, 'showInWebsite' => 1], - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, ], [ ['showInDefault' => 1, 'showInStore' => 0, 'showInWebsite' => 1], diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json index 04e2fbc1e741c134694fdd2579fc618a3bf132c4..339caeb7101710a9d1ac410ab6749ff8e3b8c5d3 100644 --- a/app/code/Magento/Config/composer.json +++ b/app/code/Magento/Config/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-cron": "0.74.0-beta6", - "magento/module-email": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-cron": "0.74.0-beta7", + "magento/module-email": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ConfigurableImportExport/composer.json b/app/code/Magento/ConfigurableImportExport/composer.json index d504ebf2a76d16c9f183cd6419774e822571e6c3..3476dfec4a07b222c02e69cb4dd2909fcabafb35 100644 --- a/app/code/Magento/ConfigurableImportExport/composer.json +++ b/app/code/Magento/ConfigurableImportExport/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-catalog-import-export": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-import-export": "0.74.0-beta6", - "magento/module-configurable-product": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-catalog-import-export": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-import-export": "0.74.0-beta7", + "magento/module-configurable-product": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php b/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php index 82e73fe8686e268e1b3701c216fe3bb8a2d4ee95..1c60ed2762efbb9c8e1a4fc6bd62c511dc98f7f1 100644 --- a/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php +++ b/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php @@ -41,17 +41,6 @@ interface OptionInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ public function setLabel($label); - /** - * @return string|null - */ - public function getType(); - - /** - * @param string $type - * @return $this - */ - public function setType($type); - /** * @return int|null */ diff --git a/app/code/Magento/ConfigurableProduct/Api/OptionTypesListInterface.php b/app/code/Magento/ConfigurableProduct/Api/OptionTypesListInterface.php deleted file mode 100644 index 0978b9c705c4933d3590a69b9454432c4cf3f0d6..0000000000000000000000000000000000000000 --- a/app/code/Magento/ConfigurableProduct/Api/OptionTypesListInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php -/** - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\ConfigurableProduct\Api; - -interface OptionTypesListInterface -{ - /** - * Get all available option types for configurable product - * - * @return string[] - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\InputException - */ - public function getItems(); -} diff --git a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php index 3e18c09648b9f9a6087e3daef9d67c1f4279b0e1..68cdb235bdeb03bd1e15e7b2146d92586236aac0 100644 --- a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php +++ b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php @@ -87,26 +87,17 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit public function get($sku, $id) { $product = $this->getProduct($sku); - $collection = $this->getConfigurableAttributesCollection($product); - $collection->addFieldToFilter($collection->getResource()->getIdFieldName(), $id); - /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $configurableAttribute */ - $configurableAttribute = $collection->getFirstItem(); - if (!$configurableAttribute->getId()) { - throw new NoSuchEntityException(__('Requested option doesn\'t exist: %1', $id)); - } - $prices = $configurableAttribute->getPrices(); - if (is_array($prices)) { - foreach ($prices as $price) { - /** @var \Magento\ConfigurableProduct\Api\Data\OptionValueInterface $value */ - $value = $this->optionValueFactory->create(); - $value->setValueIndex($price['value_index']) - ->setPricingValue($price['pricing_value']) - ->setIsPercent($price['is_percent']); - $values[] = $value; + + $extensionAttribute = $product->getExtensionAttributes(); + if ($extensionAttribute !== null) { + $options = $extensionAttribute->getConfigurableProductOptions(); + foreach ($options as $option) { + if ($option->getId() == $id) { + return $option; + } } } - $configurableAttribute->setValues($values); - return $configurableAttribute; + throw new NoSuchEntityException(__('Requested option doesn\'t exist: %1', $id)); } /** @@ -116,21 +107,10 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit { $options = []; $product = $this->getProduct($sku); - foreach ($this->getConfigurableAttributesCollection($product) as $option) { - $values = []; - $prices = $option->getPrices(); - if (is_array($prices)) { - foreach ($prices as $price) { - /** @var \Magento\ConfigurableProduct\Api\Data\OptionValueInterface $value */ - $value = $this->optionValueFactory->create(); - $value->setValueIndex($price['value_index']) - ->setPricingValue($price['pricing_value']) - ->setIsPercent($price['is_percent']); - $values[] = $value; - } - } - $option->setValues($values); - $options[] = $option; + + $extensionAttribute = $product->getExtensionAttributes(); + if ($extensionAttribute !== null) { + $options = $extensionAttribute->getConfigurableProductOptions(); } return $options; } @@ -259,17 +239,6 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit return $product; } - /** - * Retrieve configurable attribute collection through product object - * - * @param \Magento\Catalog\Model\Product $product - * @return \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Collection - */ - private function getConfigurableAttributesCollection(\Magento\Catalog\Model\Product $product) - { - return $this->configurableType->getConfigurableAttributeCollection($product); - } - /** * Ensure that all necessary data is available for a new option creation. * @@ -284,9 +253,6 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit if (!$option->getAttributeId()) { $inputException->addError(__('Option attribute ID is not specified.')); } - if (!$option->getType()) { - $inputException->addError(__('Option type is not specified.')); - } if (!$option->getLabel()) { $inputException->addError(__('Option label is not specified.')); } diff --git a/app/code/Magento/ConfigurableProduct/Model/OptionTypesList.php b/app/code/Magento/ConfigurableProduct/Model/OptionTypesList.php deleted file mode 100644 index 23b871b21248166e892ec10b45801cf1184dcf39..0000000000000000000000000000000000000000 --- a/app/code/Magento/ConfigurableProduct/Model/OptionTypesList.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\ConfigurableProduct\Model; - -class OptionTypesList implements \Magento\ConfigurableProduct\Api\OptionTypesListInterface -{ - /** - * @var \Magento\Catalog\Model\System\Config\Source\Inputtype - */ - protected $inputType; - - /** - * @param \Magento\Catalog\Model\System\Config\Source\Inputtype $inputType - */ - public function __construct(\Magento\Catalog\Model\System\Config\Source\Inputtype $inputType) - { - $this->inputType = $inputType; - } - - /** - * {@inheritdoc} - */ - public function getItems() - { - return array_map( - function ($inputType) { - return $inputType['value']; - }, - $this->inputType->toOptionArray() - ); - } -} diff --git a/app/code/Magento/ConfigurableProduct/Model/Plugin/AfterProductLoad.php b/app/code/Magento/ConfigurableProduct/Model/Plugin/AfterProductLoad.php new file mode 100644 index 0000000000000000000000000000000000000000..6bf640f16735294afeb92a35513ebbbd58e7e5f0 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Model/Plugin/AfterProductLoad.php @@ -0,0 +1,103 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Model\Plugin; + +class AfterProductLoad +{ + /** + * @var \Magento\Catalog\Api\Data\ProductExtensionFactory + */ + protected $productExtensionFactory; + + /** + * @var \Magento\ConfigurableProduct\Api\Data\OptionValueInterfaceFactory + */ + protected $optionValueFactory; + + /** + * @param \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory + * @param \Magento\ConfigurableProduct\Api\Data\OptionValueInterfaceFactory $optionValueFactory + */ + public function __construct( + \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory, + \Magento\ConfigurableProduct\Api\Data\OptionValueInterfaceFactory $optionValueFactory + ) { + $this->productExtensionFactory = $productExtensionFactory; + $this->optionValueFactory = $optionValueFactory; + } + + /** + * @param \Magento\Catalog\Model\Product $subject + * @return \Magento\Catalog\Model\Product + */ + public function afterLoad(\Magento\Catalog\Model\Product $product) + { + if ($product->getTypeId() != \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) { + return $product; + } + + $productExtension = $product->getExtensionAttributes(); + if ($productExtension === null) { + $productExtension = $this->productExtensionFactory->create(); + } + + $productExtension->setConfigurableProductOptions($this->getOptions($product)); + $productExtension->setConfigurableProductLinks($this->getLinkedProducts($product)); + + $product->setExtensionAttributes($productExtension); + + return $product; + } + + /** + * @param \Magento\Catalog\Model\Product $product + * @return \Magento\ConfigurableProduct\Api\Data\OptionInterface[] + */ + protected function getOptions(\Magento\Catalog\Model\Product $product) + { + $options = []; + /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable $typeInstance */ + $typeInstance = $product->getTypeInstance(); + $attributeCollection = $typeInstance->getConfigurableAttributes($product); + /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $option */ + foreach ($attributeCollection as $option) { + $values = []; + $prices = $option->getPrices(); + if (is_array($prices)) { + foreach ($prices as $price) { + /** @var \Magento\ConfigurableProduct\Api\Data\OptionValueInterface $value */ + $value = $this->optionValueFactory->create(); + $value->setValueIndex($price['value_index']) + ->setPricingValue($price['pricing_value']) + ->setIsPercent($price['is_percent']); + $values[] = $value; + } + } + $option->setValues($values); + $options[] = $option; + } + return $options; + } + + /** + * @param \Magento\Catalog\Model\Product $product + * @return int[] + */ + protected function getLinkedProducts(\Magento\Catalog\Model\Product $product) + { + /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable $typeInstance */ + $typeInstance = $product->getTypeInstance(); + $childrenIds = $typeInstance->getChildrenIds($product->getId()); + + if (isset($childrenIds[0])) { + return $childrenIds[0]; + } else { + return []; + } + } +} diff --git a/app/code/Magento/ConfigurableProduct/Model/Plugin/AroundProductRepositorySave.php b/app/code/Magento/ConfigurableProduct/Model/Plugin/AroundProductRepositorySave.php new file mode 100644 index 0000000000000000000000000000000000000000..f0a12b809dcd9c484b63f379c94f1749ff5d6555 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Model/Plugin/AroundProductRepositorySave.php @@ -0,0 +1,197 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Model\Plugin; + +use Magento\Framework\Exception\InputException; + +class AroundProductRepositorySave +{ + /** + * @var \Magento\ConfigurableProduct\Api\OptionRepositoryInterface + */ + protected $optionRepository; + + /** + * @var \Magento\Catalog\Model\ProductFactory + */ + protected $productFactory; + + /** + * Type configurable factory + * + * @var \Magento\ConfigurableProduct\Model\Resource\Product\Type\ConfigurableFactory + */ + protected $typeConfigurableFactory; + + /* + * @var \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Price\Data + */ + protected $priceData; + + /** + * @param \Magento\ConfigurableProduct\Api\OptionRepositoryInterface $optionRepository + * @param \Magento\Catalog\Model\ProductFactory $productFactory + * @param \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Price\Data $priceData + * @param \Magento\ConfigurableProduct\Model\Resource\Product\Type\ConfigurableFactory $typeConfigurableFactory + */ + public function __construct( + \Magento\ConfigurableProduct\Api\OptionRepositoryInterface $optionRepository, + \Magento\Catalog\Model\ProductFactory $productFactory, + \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Price\Data $priceData, + \Magento\ConfigurableProduct\Model\Resource\Product\Type\ConfigurableFactory $typeConfigurableFactory + ) { + $this->optionRepository = $optionRepository; + $this->productFactory = $productFactory; + $this->priceData = $priceData; + $this->typeConfigurableFactory = $typeConfigurableFactory; + } + + /** + * @param \Magento\Catalog\Api\ProductRepositoryInterface $subject + * @param callable $proceed + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param bool $saveOptions + * @return \Magento\Catalog\Api\Data\ProductInterface + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundSave( + \Magento\Catalog\Api\ProductRepositoryInterface $subject, + \Closure $proceed, + \Magento\Catalog\Api\Data\ProductInterface $product, + $saveOptions = false + ) { + /** @var \Magento\Catalog\Api\Data\ProductInterface $result */ + $result = $proceed($product, $saveOptions); + + if ($product->getTypeId() != \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) { + return $result; + } + + $extendedAttributes = $product->getExtensionAttributes(); + if ($extendedAttributes === null) { + return $result; + } + $configurableProductOptions = $extendedAttributes->getConfigurableProductOptions(); + $configurableProductLinks = $extendedAttributes->getConfigurableProductLinks(); + if ($configurableProductOptions === null && $configurableProductLinks === null) { + return $result; + } + if ($configurableProductOptions !== null) { + $this->saveConfigurableProductOptions($result, $configurableProductOptions); + $result->getTypeInstance()->resetConfigurableAttributes($result); + } + if ($configurableProductLinks !== null) { + $this->saveConfigurableProductLinks($result, $configurableProductLinks); + } + $this->priceData->setProductPrice($result->getId(), null); + return $subject->get($result->getSku(), false, $result->getStoreId(), true); + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param \Magento\ConfigurableProduct\Api\Data\OptionInterface[] $options + * @return $this + */ + protected function saveConfigurableProductOptions( + \Magento\Catalog\Api\Data\ProductInterface $product, + array $options + ) { + $existingOptionIds = []; + if ($product->getExtensionAttributes() !== null) { + $extensionAttributes = $product->getExtensionAttributes(); + if ($extensionAttributes->getConfigurableProductOptions() !== null) { + $existingOptions = $extensionAttributes->getConfigurableProductOptions(); + foreach ($existingOptions as $option) { + $existingOptionIds[] = $option->getId(); + } + } + } + + $updatedOptionIds = []; + foreach ($options as $option) { + if ($option->getId()) { + $updatedOptionIds[] = $option->getId(); + } + $this->optionRepository->save($product->getSku(), $option); + } + + $optionIdsToDelete = array_diff($existingOptionIds, $updatedOptionIds); + foreach ($optionIdsToDelete as $optionId) { + $this->optionRepository->deleteById($product->getSku(), $optionId); + } + return $this; + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param int[] $linkIds + * @return $this + */ + protected function saveConfigurableProductLinks( + \Magento\Catalog\Api\Data\ProductInterface $product, + array $linkIds + ) { + $configurableProductTypeResource = $this->typeConfigurableFactory->create(); + if (!empty($linkIds)) { + /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableProductType */ + $configurableProductType = $product->getTypeInstance(); + $configurableAttributes = $configurableProductType->getConfigurableAttributes($product); + $attributeCodes = []; + foreach ($configurableAttributes as $configurableAttribute) { + /** @var \Magento\Catalog\Model\Resource\Eav\Attribute $productAttribute */ + $productAttribute = $configurableAttribute->getProductAttribute(); + $attributeCode = $productAttribute->getAttributeCode(); + $attributeCodes[] = $attributeCode; + } + $this->validateProductLinks($attributeCodes, $linkIds); + } + + $configurableProductTypeResource->saveProducts($product, $linkIds); + return $this; + } + + /** + * @param array $attributeCodes + * @param array $linkIds + * @throws InputException + * @return $this + */ + protected function validateProductLinks(array $attributeCodes, array $linkIds) + { + $valueMap = []; + if (empty($attributeCodes) && !empty($linkIds)) { + throw new InputException( + __('The configurable product does not have any variation attribute.') + ); + } + + foreach ($linkIds as $productId) { + $variation = $this->productFactory->create()->load($productId); + if (!$variation->getId()) { + throw new InputException(__('Product with id "%1" does not exist.', $productId)); + } + $valueKey = ''; + foreach ($attributeCodes as $attributeCode) { + if (!$variation->getData($attributeCode)) { + throw new InputException( + __('Product with id "%1" does not contain required attribute "%2".', $productId, $attributeCode) + ); + } + $valueKey = $valueKey . $attributeCode . ':' . $variation->getData($attributeCode) . ';'; + } + if (isset($valueMap[$valueKey])) { + throw new InputException( + __('Products "%1" and %2 have the same set of attribute values.', $productId, $valueMap[$valueKey]) + ); + } + $valueMap[$valueKey] = $productId; + } + return $this; + } +} diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index 5922c01bad8a3868bd867b8bd1522d3b2593ef30..c1fb0b41ef427e758954ee9728084e67eb9c5bed 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -377,6 +377,18 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType return $product->getData($this->_configurableAttributes); } + /** + * Reset the cached configurable attributes of a product + * + * @param \Magento\Catalog\Model\Product $product + * @return $this + */ + public function resetConfigurableAttributes($product) + { + $product->unsetData($this->_configurableAttributes); + return $this; + } + /** * Retrieve Configurable Attributes as array * diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index f02e39626d66a7571bea42e1c5b2b1af804caf9c..8cf22a9b6dc3b4127baa3b8e9c8e5a9c0ade4dce 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -24,7 +24,6 @@ class Attribute extends \Magento\Framework\Model\AbstractExtensibleModel impleme */ const KEY_ATTRIBUTE_ID = 'attribute_id'; const KEY_LABEL = 'label'; - const KEY_TYPE = 'type'; const KEY_POSITION = 'position'; const KEY_IS_USE_DEFAULT = 'is_use_default'; const KEY_VALUES = 'values'; @@ -119,15 +118,6 @@ class Attribute extends \Magento\Framework\Model\AbstractExtensibleModel impleme return $this->getData(self::KEY_ATTRIBUTE_ID); } - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getType() - { - return $this->getData(self::KEY_TYPE); - } - /** * {@inheritdoc} * @codeCoverageIgnore @@ -174,15 +164,6 @@ class Attribute extends \Magento\Framework\Model\AbstractExtensibleModel impleme return $this->setData(self::KEY_LABEL, $label); } - /** - * @param string $type - * @return $this - */ - public function setType($type) - { - return $this->setData(self::KEY_TYPE, $type); - } - /** * @param int $position * @return $this diff --git a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable.php index e556661f45b1a802fd4f9024cbcbbd4889653cd0..671aa6b136ab40b63ad67c9f7229dcdb7a8ae1f9 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable.php @@ -180,10 +180,6 @@ class Configurable extends \Magento\Framework\Model\Resource\Db\AbstractDb implode( ' AND ', [ - $this->_getReadAdapter()->quoteInto( - 'entity_value.entity_type_id = ?', - $product->getEntityTypeId() - ), 'entity_value.attribute_id = super_attribute.attribute_id', 'entity_value.store_id = 0', 'entity_value.entity_id = product_link.product_id' diff --git a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php index 9d2ca8b5414c7920d4fb9235e6c6eaaaf4882368..f10a02db96f2297d1050a322c9bb92eaaa28cb91 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php @@ -263,7 +263,12 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac $values = $this->getPriceValues(); foreach ($values as $data) { - $this->getItemById($data['product_super_attribute_id'])->addPrice($data); + $item = $this->getItemById($data['product_super_attribute_id']); + //the price values is cached, it could have gotten out of sync with current items + //when a filter is added, in that case, we just ignore the data from the cache + if ($item) { + $item->addPrice($data); + } } } return $this; diff --git a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Price/Data.php b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Price/Data.php index 248ed3ede9f343883132711c056d9966431c763e..3e5c714e425e4d50f4eec11eb6f1a09879c1ec87 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Price/Data.php +++ b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Price/Data.php @@ -24,10 +24,10 @@ class Data /** * @param int $productId - * @param array $priceData + * @param array|null $priceData * @return void */ - public function setProductPrice($productId, array $priceData) + public function setProductPrice($productId, array $priceData = null) { $this->prices[$productId] = $priceData; } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..34b66ecb320dc65bed96338f0435a8253b7aca5b --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php @@ -0,0 +1,210 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Test\Unit\Model; + +class OptionRepositoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\ConfigurableProduct\Model\OptionRepository + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + protected function setUp() + { + $this->productRepositoryMock = $this->getMock('\Magento\Catalog\Api\ProductRepositoryInterface'); + $this->productMock = $this->getMock('\Magento\Catalog\Api\Data\ProductInterface'); + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $objectManager->getObject( + '\Magento\ConfigurableProduct\Model\OptionRepository', + [ + 'productRepository' => $this->productRepositoryMock, + ] + ); + } + + public function testGet() + { + $productSku = "configurable"; + $optionId = 3; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + + $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); + $optionMock->expects($this->once()) + ->method('getId') + ->willReturn($optionId); + $productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['getConfigurableProductOptions']) + ->getMock(); + $productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn([$optionMock]); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($productExtensionMock); + + $this->assertEquals($optionMock, $this->model->get($productSku, $optionId)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Only implemented for configurable product: configurable + */ + public function testGetNotConfigurableProduct() + { + $productSku = "configurable"; + $optionId = 3; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn('simple'); + + $this->model->get($productSku, $optionId); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested option doesn't exist: 3 + */ + public function testGetEmptyExtensionAttribute() + { + $productSku = "configurable"; + $optionId = 3; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn(null); + + $this->model->get($productSku, $optionId); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested option doesn't exist: 3 + */ + public function testGetOptionIdNotFound() + { + $productSku = "configurable"; + $optionId = 3; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + + $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); + $optionMock->expects($this->once()) + ->method('getId') + ->willReturn(6); + $productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['getConfigurableProductOptions']) + ->getMock(); + $productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn([$optionMock]); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($productExtensionMock); + + $this->model->get($productSku, $optionId); + } + + public function testGetList() + { + $productSku = "configurable"; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + + $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); + $productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['getConfigurableProductOptions']) + ->getMock(); + $productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn([$optionMock]); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($productExtensionMock); + + $this->assertEquals([$optionMock], $this->model->getList($productSku)); + } + + public function testGetListNullExtensionAttribute() + { + $productSku = "configurable"; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn(null); + + $this->assertEquals([], $this->model->getList($productSku)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Only implemented for configurable product: configurable + */ + public function testGetListNotConfigurableProduct() + { + $productSku = "configurable"; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn('simple'); + + $this->model->getList($productSku); + } +} diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionTypesListTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionTypesListTest.php deleted file mode 100644 index 79867bb302e321ff1da0c4e887a1d2f754bb115b..0000000000000000000000000000000000000000 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionTypesListTest.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\ConfigurableProduct\Test\Unit\Model; - -class OptionTypesListTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var OptionTypesList - */ - protected $model; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $sourceMock; - - protected function setUp() - { - $this->sourceMock = $this->getMock('\Magento\Catalog\Model\System\Config\Source\Inputtype', [], [], '', false); - $this->model = new \Magento\ConfigurableProduct\Model\OptionTypesList($this->sourceMock); - } - - public function testGetItems() - { - $data = [ - ['value' => 'multiselect', 'label' => __('Multiple Select')], - ['value' => 'select', 'label' => __('Dropdown')] - ]; - $this->sourceMock->expects($this->once())->method('toOptionArray')->willReturn($data); - $expected = ['multiselect', 'select']; - $this->assertEquals($expected, $this->model->getItems()); - } -} diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AfterProductLoadTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AfterProductLoadTest.php new file mode 100644 index 0000000000000000000000000000000000000000..af3e73f0b855eeddb16f965f7438d8a16cbcd601 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AfterProductLoadTest.php @@ -0,0 +1,239 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Test\Unit\Model\Plugin; + +use Magento\ConfigurableProduct\Model\Plugin\AfterProductLoad; + +class AfterProductLoadTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var AfterProductLoad + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $optionValueFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Magento\Catalog\Model\Product + */ + protected $productMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $configurableProductTypeInstanceMock; + + protected function setUp() + { + $this->optionValueFactory = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Api\Data\OptionValueInterfaceFactory' + )->disableOriginalConstructor()->getMock(); + $this->productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + $this->configurableProductTypeInstanceMock = $this->getMock( + '\Magento\ConfigurableProduct\Model\Product\Type\Configurable', + [], + [], + '', + false + ); + $this->productMock->expects($this->any()) + ->method('getTypeInstance') + ->willReturn($this->configurableProductTypeInstanceMock); + $this->productExtensionFactory = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtensionFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new \Magento\ConfigurableProduct\Model\Plugin\AfterProductLoad( + $this->productExtensionFactory, + $this->optionValueFactory + ); + } + + protected function setupOptions() + { + $optionValues = [ + [ + 'value_index' => 5, + 'pricing_value' => 10, + 'is_percent' => 0, + ], + [ + 'value_index' => 6, + 'pricing_value' => 5, + 'is_percent' => 1, + ], + ]; + $optionMock1 = $this->getMockBuilder('\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute') + ->disableOriginalConstructor() + ->setMethods(['getPrices', 'setValues']) + ->getMock(); + $optionMock1->expects($this->once()) + ->method('getPrices') + ->willReturn($optionValues); + + $optionValueMock1 = $this->getMockBuilder('\Magento\ConfigurableProduct\Api\Data\OptionValueInterface') + ->disableOriginalConstructor() + ->getMock(); + $optionValueMock1->expects($this->once()) + ->method('setValueIndex') + ->with($optionValues[0]['value_index']) + ->willReturnSelf(); + $optionValueMock1->expects($this->once()) + ->method('setPricingValue') + ->with($optionValues[0]['pricing_value']) + ->willReturnSelf(); + $optionValueMock1->expects($this->once()) + ->method('setIsPercent') + ->with($optionValues[0]['is_percent']) + ->willReturnSelf(); + + $optionValueMock2 = $this->getMockBuilder('\Magento\ConfigurableProduct\Api\Data\OptionValueInterface') + ->disableOriginalConstructor() + ->getMock(); + $optionValueMock2->expects($this->once()) + ->method('setValueIndex') + ->with($optionValues[1]['value_index']) + ->willReturnSelf(); + $optionValueMock2->expects($this->once()) + ->method('setPricingValue') + ->with($optionValues[1]['pricing_value']) + ->willReturnSelf(); + $optionValueMock2->expects($this->once()) + ->method('setIsPercent') + ->with($optionValues[1]['is_percent']) + ->willReturnSelf(); + + $this->optionValueFactory->expects($this->at(0)) + ->method('create') + ->willReturn($optionValueMock1); + $optionMock1->expects($this->once()) + ->method('setValues') + ->with([$optionValueMock1, $optionValueMock2]); + + $optionMock2 = $this->getMockBuilder('\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute') + ->disableOriginalConstructor() + ->setMethods(['getPrices', 'setValues']) + ->getMock(); + $optionMock2->expects($this->once()) + ->method('getPrices') + ->willReturn([]); + $optionMock2->expects($this->once()) + ->method('setValues') + ->with([]); + $this->optionValueFactory->expects($this->at(1)) + ->method('create') + ->willReturn($optionValueMock2); + + $options = [$optionMock1, $optionMock2]; + + $this->configurableProductTypeInstanceMock->expects($this->once()) + ->method('getConfigurableAttributes') + ->with($this->productMock) + ->willReturn($options); + return $options; + } + + protected function setupLinks() + { + $id = 5; + $links = [6, 7]; + $this->productMock->expects($this->once()) + ->method('getId') + ->willReturn($id); + $this->configurableProductTypeInstanceMock->expects($this->once()) + ->method('getChildrenIds') + ->with($id) + ->willReturn([$links]); + return $links; + } + + public function testAfterLoad() + { + $options = $this->setupOptions(); + $links = $this->setupLinks(); + + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + + $extensionAttributeMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['setConfigurableProductOptions', 'setConfigurableProductLinks']) + ->getMock(); + + $extensionAttributeMock->expects($this->once())->method('setConfigurableProductOptions') + ->with($options) + ->willReturnSelf(); + $extensionAttributeMock->expects($this->once())->method('setConfigurableProductLinks') + ->with($links) + ->willReturnSelf(); + + $this->productExtensionFactory->expects($this->once()) + ->method('create') + ->willReturn($extensionAttributeMock); + + $this->productMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($extensionAttributeMock) + ->willReturnSelf(); + + $this->assertEquals($this->productMock, $this->model->afterLoad($this->productMock)); + } + + public function testAfterLoadNotConfigurableProduct() + { + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn('simple'); + + $this->productMock->expects($this->never()) + ->method('getExtensionAttributes'); + $this->productMock->expects($this->never()) + ->method('setExtensionAttributes'); + $this->assertEquals($this->productMock, $this->model->afterLoad($this->productMock)); + } + + public function testAfterLoadNoLinks() + { + $options = $this->setupOptions(); + + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + + $extensionAttributeMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['setConfigurableProductOptions', 'setConfigurableProductLinks']) + ->getMock(); + + $extensionAttributeMock->expects($this->once())->method('setConfigurableProductOptions') + ->with($options) + ->willReturnSelf(); + $extensionAttributeMock->expects($this->once())->method('setConfigurableProductLinks') + ->with([]) + ->willReturnSelf(); + + $this->productExtensionFactory->expects($this->once()) + ->method('create') + ->willReturn($extensionAttributeMock); + + $this->productMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($extensionAttributeMock) + ->willReturnSelf(); + + $this->assertEquals($this->productMock, $this->model->afterLoad($this->productMock)); + } +} diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6e750f9e13fcee390a5ae1a4fab496a507816f6c --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php @@ -0,0 +1,553 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Test\Unit\Model\Plugin; + +use Magento\ConfigurableProduct\Model\Plugin\AroundProductRepositorySave; + +class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var AroundProductRepositorySave + */ + protected $plugin; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productOptionRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $configurableTypeFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $priceDataMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productInterfaceMock; + + /** + * @var \Closure + */ + protected $closureMock; + + protected function setUp() + { + $this->productRepositoryMock = $this->getMock('Magento\Catalog\Api\ProductRepositoryInterface'); + $this->productOptionRepositoryMock = $this->getMock( + 'Magento\ConfigurableProduct\Api\OptionRepositoryInterface' + ); + $this->configurableTypeFactoryMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Resource\Product\Type\ConfigurableFactory' + )->disableOriginalConstructor()->getMock(); + $this->priceDataMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Price\Data' + )->disableOriginalConstructor()->getMock(); + $this->productInterfaceMock = $this->getMock('\Magento\Catalog\Api\Data\ProductInterface'); + $this->productMock = $this->getMock( + 'Magento\Catalog\Model\Product', + ['getExtensionAttributes', 'getTypeId', 'getSku', 'getStoreId', 'getId', 'getTypeInstance'], + [], + '', + false + ); + $this->closureMock = function () { + return $this->productMock; + }; + + $this->productFactoryMock = $this->getMockBuilder('\Magento\Catalog\Model\ProductFactory') + ->disableOriginalConstructor() + ->getMock(); + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->plugin = $objectManager->getObject( + 'Magento\ConfigurableProduct\Model\Plugin\AroundProductRepositorySave', + [ + 'optionRepository' => $this->productOptionRepositoryMock, + 'productFactory' => $this->productFactoryMock, + 'priceData' => $this->priceDataMock, + 'typeConfigurableFactory' => $this->configurableTypeFactoryMock + ] + ); + + $this->productExtensionMock = $this->getMock( + 'Magento\Catalog\Api\Data\ProductExtension', + [ + 'getConfigurableProductOptions', + 'getConfigurableProductLinks', + 'setConfigurableProductOptions', + 'setConfigurableProductLinks', + ], + [], + '', + false + ); + } + + public function testAroundSaveWhenProductIsSimple() + { + $this->productMock->expects($this->once())->method('getTypeId')->willReturn('simple'); + $this->productMock->expects($this->never())->method('getExtensionAttributes'); + + $this->assertEquals( + $this->productMock, + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + public function testAroundSaveWithoutOptions() + { + $this->productInterfaceMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + $this->productInterfaceMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductLinks') + ->willReturn(null); + + $this->priceDataMock->expects($this->never()) + ->method('setProductPrice'); + + $this->assertEquals( + $this->productMock, + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productInterfaceMock) + ); + } + + protected function setupProducts($productIds, $attributeCode, $additionalProductId = null) + { + $count = 0; + $products = []; + foreach ($productIds as $productId) { + $productMock = $this->getMockBuilder('\Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + $productMock->expects($this->once()) + ->method('load') + ->with($productId) + ->willReturnSelf(); + $productMock->expects($this->once()) + ->method('getId') + ->willReturn($productId); + $productMock->expects($this->any()) + ->method('getData') + ->with($attributeCode) + ->willReturn($productId); + $this->productFactoryMock->expects($this->at($count)) + ->method('create') + ->willReturn($productMock); + $products[] = $productMock; + $count++; + } + + if ($additionalProductId) { + $nonExistingProductMock = $this->getMockBuilder('\Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + $nonExistingProductMock->expects($this->once()) + ->method('load') + ->with($additionalProductId) + ->willReturnSelf(); + $this->productFactoryMock->expects($this->at($count)) + ->method('create') + ->willReturn($nonExistingProductMock); + $products[] = $nonExistingProductMock; + } + return $products; + } + + protected function setupConfigurableProductAttributes($attributeCodes) + { + $configurableProductTypeMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Product\Type\Configurable' + )->disableOriginalConstructor()->getMock(); + + $this->productMock->expects($this->once()) + ->method('getTypeInstance') + ->willReturn($configurableProductTypeMock); + + $configurableAttributes = []; + foreach ($attributeCodes as $attributeCode) { + $configurableAttribute = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute' + )->setMethods(['getProductAttribute']) + ->disableOriginalConstructor() + ->getMock(); + $productAttributeMock = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Eav\Attribute') + ->disableOriginalConstructor() + ->getMock(); + $productAttributeMock->expects($this->once()) + ->method('getAttributeCode') + ->willReturn($attributeCode); + $configurableAttribute->expects($this->once()) + ->method('getProductAttribute') + ->willReturn($productAttributeMock); + $configurableAttributes[] = $configurableAttribute; + } + + $configurableProductTypeMock->expects($this->once()) + ->method('getConfigurableAttributes') + ->with($this->productMock) + ->willReturn($configurableAttributes); + + return $this; + } + + public function testAroundSaveWithLinks() + { + $links = [4, 5]; + $configurableAttributeCode = 'color'; + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductLinks') + ->willReturn($links); + + $this->setupConfigurableProductAttributes([$configurableAttributeCode]); + $this->setupProducts($links, $configurableAttributeCode); + + $configurableTypeMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable' + )->disableOriginalConstructor()->getMock(); + $this->configurableTypeFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($configurableTypeMock); + $configurableTypeMock->expects($this->once()) + ->method('saveProducts') + ->with($this->productMock, $links); + + $productId = 3; + $this->productMock->expects($this->any()) + ->method('getId') + ->willReturn($productId); + $this->priceDataMock->expects($this->once()) + ->method('setProductPrice') + ->with($productId, null); + + $productSku = 'configurable-sku'; + $this->productMock->expects($this->any()) + ->method('getSku') + ->willReturn($productSku); + $newProductMock = $this->setupReload($productSku); + + $this->assertEquals( + $newProductMock, + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Product with id "6" does not exist. + */ + public function testAroundSaveWithNonExistingLinks() + { + $links = [4, 5]; + $nonExistingId = 6; + $configurableAttributeCode = 'color'; + + $this->setupConfigurableProductAttributes([$configurableAttributeCode]); + $productMocks = $this->setupProducts($links, $configurableAttributeCode, $nonExistingId); + $nonExistingProductMock = $productMocks[2]; + $nonExistingProductMock->expects($this->once()) + ->method('getId') + ->willReturn(null); + $links[] = $nonExistingId; + + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductLinks') + ->willReturn($links); + + $configurableTypeMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable' + )->disableOriginalConstructor()->getMock(); + $this->configurableTypeFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($configurableTypeMock); + $configurableTypeMock->expects($this->never()) + ->method('saveProducts') + ->with($this->productMock, $links); + + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Product with id "6" does not contain required attribute "color". + */ + public function testAroundSaveWithLinksWithMissingAttribute() + { + $links = [4, 5]; + $simpleProductId = 6; + $configurableAttributeCode = 'color'; + + $this->setupConfigurableProductAttributes([$configurableAttributeCode]); + $productMocks = $this->setupProducts($links, $configurableAttributeCode, $simpleProductId); + $simpleProductMock = $productMocks[2]; + $simpleProductMock->expects($this->once()) + ->method('getId') + ->willReturn($simpleProductId); + $simpleProductMock->expects($this->any()) + ->method('getData') + ->with($configurableAttributeCode) + ->willReturn(null); + + $links[] = $simpleProductId; + + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductLinks') + ->willReturn($links); + + $configurableTypeMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable' + )->disableOriginalConstructor()->getMock(); + $this->configurableTypeFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($configurableTypeMock); + $configurableTypeMock->expects($this->never()) + ->method('saveProducts') + ->with($this->productMock, $links); + + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Products "6" and 4 have the same set of attribute values. + */ + public function testAroundSaveWithLinksWithDuplicateAttributes() + { + $links = [4, 5]; + $simpleProductId = 6; + $configurableAttributeCode = 'color'; + + $this->setupConfigurableProductAttributes([$configurableAttributeCode]); + $productMocks = $this->setupProducts($links, $configurableAttributeCode, $simpleProductId); + $simpleProductMock = $productMocks[2]; + $simpleProductMock->expects($this->once()) + ->method('getId') + ->willReturn($simpleProductId); + $simpleProductMock->expects($this->any()) + ->method('getData') + ->with($configurableAttributeCode) + ->willReturn(4); + + $links[] = $simpleProductId; + + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductLinks') + ->willReturn($links); + + $configurableTypeMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable' + )->disableOriginalConstructor()->getMock(); + $this->configurableTypeFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($configurableTypeMock); + $configurableTypeMock->expects($this->never()) + ->method('saveProducts') + ->with($this->productMock, $links); + + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage The configurable product does not have any variation attribute. + */ + public function testAroundSaveWithLinksWithoutVariationAttributes() + { + $links = [4, 5]; + + $this->setupConfigurableProductAttributes([]); + + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductOptions') + ->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getConfigurableProductLinks') + ->willReturn($links); + + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock); + } + + public function testAroundSaveWithOptions() + { + $productSku = "configurable_sku"; + $this->productInterfaceMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + //two options with id 5 and 6 + $options = $this->setupOptions([5, 6]); + //two existing options with id 4 and 5 + $this->setupExistingOptions([4, 5]); + + $this->productMock->expects($this->any())->method('getSku') + ->will($this->returnValue($productSku)); + + $this->productOptionRepositoryMock->expects($this->at(0)) + ->method('save') + ->with($productSku, $options[0]); + $this->productOptionRepositoryMock->expects($this->at(1)) + ->method('save') + ->with($productSku, $options[1]); + $this->productOptionRepositoryMock->expects($this->at(2)) + ->method('deleteById') + ->with($productSku, 4); + + $configurableProductTypeMock = $this->getMockBuilder( + '\Magento\ConfigurableProduct\Model\Product\Type\Configurable' + )->disableOriginalConstructor()->getMock(); + $configurableProductTypeMock->expects($this->once()) + ->method('resetConfigurableAttributes') + ->with($this->productMock) + ->willReturnSelf(); + $this->productMock->expects($this->any()) + ->method('getTypeInstance') + ->willReturn($configurableProductTypeMock); + + $productId = 3; + $this->productMock->expects($this->once()) + ->method('getId') + ->willReturn($productId); + $this->priceDataMock->expects($this->once()) + ->method('setProductPrice') + ->with($productId, null); + + $newProductMock = $this->setupReload($productSku); + + $this->assertEquals( + $newProductMock, + $this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productInterfaceMock) + ); + } + + protected function setupReload($productSku) + { + $newProductMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface') + ->disableOriginalConstructor()->getMock(); + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku, false, null, true) + ->willReturn($newProductMock); + return $newProductMock; + } + + protected function setupExistingOptions(array $existingOptionIds) + { + $options = []; + foreach ($existingOptionIds as $existingOptionId) { + $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); + $optionMock->expects($this->any()) + ->method('getId') + ->willReturn($existingOptionId); + $options[] = $optionMock; + } + + $productExtensionMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductExtension') + ->disableOriginalConstructor() + ->setMethods(['getConfigurableProductOptions']) + ->getMock(); + $productExtensionMock->expects($this->any()) + ->method('getConfigurableProductOptions') + ->willReturn($options); + + $this->productMock->expects($this->any()) + ->method('getExtensionAttributes') + ->willReturn($productExtensionMock); + } + + protected function setupOptions(array $optionIds) + { + $options = []; + foreach ($optionIds as $optionId) { + $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); + $optionMock->expects($this->any()) + ->method('getId') + ->willReturn($optionId); + $options[] = $optionMock; + } + + $productExtensionMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductExtension') + ->disableOriginalConstructor() + ->setMethods(['getConfigurableProductOptions', 'getConfigurableProductLinks']) + ->getMock(); + $productExtensionMock->expects($this->any()) + ->method('getConfigurableProductOptions') + ->willReturn($options); + $productExtensionMock->expects($this->any()) + ->method('getConfigurableProductLinks') + ->willReturn(null); + + $this->productInterfaceMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($productExtensionMock); + return $options; + } +} diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php index d0c5ae32ab1dc80a675f55233119de9eedcdc708..4ca090adef44b5e3786bd066067c7c6aaa03ac53 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php @@ -408,6 +408,19 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ]; } + public function testResetConfigurableAttributes() + { + $product = $this->getMockBuilder('\Magento\Catalog\Model\Product') + ->setMethods(['unsetData', '__wakeup', '__sleep']) + ->disableOriginalConstructor() + ->getMock(); + $product->expects($this->any())->method('unsetData') + ->with('_cache_instance_configurable_attributes') + ->will($this->returnSelf()); + + $this->assertEquals($this->_model, $this->_model->resetConfigurableAttributes($product)); + } + public function testHasOptions() { $productMock = $this->getMockBuilder('\Magento\Catalog\Model\Product') @@ -584,10 +597,6 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ->setMethods(['getId', 'getAttributeCode']) ->disableOriginalConstructor() ->getMock(); - $productResource = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Product') - ->setMethods(['__wakeup', 'loadAllAttributes', 'getSortedAttributes']) - ->disableOriginalConstructor() - ->getMock(); $productCollection = $this->getMockBuilder( 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\Collection' ) @@ -616,14 +625,12 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ->method('getData') ->with('_cache_instance_store_filter') ->willReturn('some_filter'); - $productMock->expects($this->once())->method('hasData')->willReturn(true); - $productMock->expects($this->at(3))->method('getData')->willReturn([$usedProductMock]); - $productMock->expects($this->once())->method('getResource')->willReturn($productResource); - $productMock->expects($this->once())->method('getAttributeSetId')->willReturn(5); - $productResource->expects($this->once())->method('loadAllAttributes')->with($productMock)->willReturnSelf(); - $productResource->expects($this->once()) - ->method('getSortedAttributes') - ->with(5) + $productMock->expects($this->any())->method('hasData')->willReturn(true); + $productMock->expects($this->at(3))->method('getData') + ->with('_cache_instance_products') + ->willReturn([$usedProductMock]); + $productMock->expects($this->at(5))->method('getData') + ->with('_cache_instance_product_set_attributes') ->willReturn([$eavAttributeMock]); $eavAttributeMock->expects($this->once())->method('getId')->willReturn(1); $eavAttributeMock->expects($this->once())->method('getAttributeCode')->willReturn('attr_code'); diff --git a/app/code/Magento/ConfigurableProduct/composer.json b/app/code/Magento/ConfigurableProduct/composer.json index 507ee995f908bde44cc3f29647133573e35de89c..e39bfede226336143aab79ade959eb6ccfb71b39 100644 --- a/app/code/Magento/ConfigurableProduct/composer.json +++ b/app/code/Magento/ConfigurableProduct/composer.json @@ -3,26 +3,26 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-catalog-rule": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-catalog-rule": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-webapi": "0.74.0-beta6" + "magento/module-webapi": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index fcd5d77b81e4de8e9a5df180968909b02d290221..490c15a70a51fc150d80d3e8b42dd5c4ef8aa47e 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -6,7 +6,6 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> - <preference for="Magento\ConfigurableProduct\Api\OptionTypesListInterface" type="Magento\ConfigurableProduct\Model\OptionTypesList" /> <preference for="Magento\ConfigurableProduct\Api\ConfigurableProductManagementInterface" type="Magento\ConfigurableProduct\Model\ConfigurableProductManagement" /> <preference for="Magento\ConfigurableProduct\Api\LinkManagementInterface" type="Magento\ConfigurableProduct\Model\LinkManagement" /> <preference for="Magento\ConfigurableProduct\Api\OptionRepositoryInterface" type="Magento\ConfigurableProduct\Model\OptionRepository" /> @@ -59,6 +58,12 @@ <type name="Magento\Catalog\Model\Product\Type"> <plugin name="configurable_output" type="Magento\ConfigurableProduct\Model\Product\Type\Plugin" /> </type> + <type name="Magento\Catalog\Api\ProductRepositoryInterface"> + <plugin name="configurableProductSaveOptions" type="\Magento\ConfigurableProduct\Model\Plugin\AroundProductRepositorySave"/> + </type> + <type name="Magento\Catalog\Model\Product"> + <plugin name="configurableProductLoadAfter" type="\Magento\ConfigurableProduct\Model\Plugin\AfterProductLoad"/> + </type> <virtualType name="Magento\ConfigurableProduct\Pricing\Price\Pool" type="Magento\Framework\Pricing\Price\Pool"> <arguments> <argument name="prices" xsi:type="array"> diff --git a/app/code/Magento/ConfigurableProduct/etc/service_data_attributes.xml b/app/code/Magento/ConfigurableProduct/etc/service_data_attributes.xml new file mode 100644 index 0000000000000000000000000000000000000000..74edcdbf65a91e08cc384b50b416deff63e8780c --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/etc/service_data_attributes.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> + <attribute code="configurable_product_options" type="Magento\ConfigurableProduct\Api\Data\OptionInterface[]" /> + <attribute code="configurable_product_links" type="int[]" /> + </extension_attributes> +</config> diff --git a/app/code/Magento/ConfigurableProduct/etc/webapi.xml b/app/code/Magento/ConfigurableProduct/etc/webapi.xml index 9c68aa71869f44782120dda382eb7de6c34e9f2d..158db3c3c5fa8313960e1735250f3f7cfb250388 100644 --- a/app/code/Magento/ConfigurableProduct/etc/webapi.xml +++ b/app/code/Magento/ConfigurableProduct/etc/webapi.xml @@ -43,12 +43,6 @@ <resource ref="Magento_Catalog::products"/> </resources> </route> - <route url="/V1/configurable-products/options/types" method="GET"> - <service class="Magento\ConfigurableProduct\Api\OptionTypesListInterface" method="getItems" /> - <resources> - <resource ref="Magento_Catalog::products" /> - </resources> - </route> <route url="/V1/configurable-products/:sku/options" method="POST"> <service class="Magento\ConfigurableProduct\Api\OptionRepositoryInterface" method="save" /> <resources> diff --git a/app/code/Magento/Contact/composer.json b/app/code/Magento/Contact/composer.json index d2e5971064d0752a9053de71ef835fa13f07b6db..3918d730162140a6d4a43c0d3f867d04160a7da7 100644 --- a/app/code/Magento/Contact/composer.json +++ b/app/code/Magento/Contact/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cookie/composer.json b/app/code/Magento/Cookie/composer.json index d3d5ef16f597b19653d8a69ff3e597bca16d30bf..e9fbc65e8fe32e9286593292ffb40f6f2c373af3 100644 --- a/app/code/Magento/Cookie/composer.json +++ b/app/code/Magento/Cookie/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.4.11|~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-backend": "0.74.0-beta6" + "magento/module-backend": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cron/composer.json b/app/code/Magento/Cron/composer.json index 02fe4b2ed4e83bb3de474176d18e622266e9552d..a1fbef449d8300e48de58421c67bd96cd716ea89 100644 --- a/app/code/Magento/Cron/composer.json +++ b/app/code/Magento/Cron/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CurrencySymbol/composer.json b/app/code/Magento/CurrencySymbol/composer.json index 4ef0b1acf67493b6de9ff927c58ba3ad8ae97166..6f862fbf51bd05c47a100f58df52d9d7580bb902 100644 --- a/app/code/Magento/CurrencySymbol/composer.json +++ b/app/code/Magento/CurrencySymbol/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-page-cache": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-page-cache": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/BackButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/BackButton.php index ee99e417ad351ce4007b26d8119a590a5c7daa38..20d5ffa53787e68ab33e50a594401856af4dcec5 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/BackButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/BackButton.php @@ -5,11 +5,10 @@ */ namespace Magento\Customer\Block\Adminhtml\Edit; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class BackButton - * @package Magento\Customer\Block\Adminhtml\Edit */ class BackButton extends GenericButton implements ButtonProviderInterface { @@ -20,7 +19,7 @@ class BackButton extends GenericButton implements ButtonProviderInterface { return [ 'label' => __('Back'), - 'on_click' => 'setLocation(\'' . $this->getBackUrl() . '\')', + 'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()), 'class' => 'back', 'sort_order' => 10 ]; diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/DeleteButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/DeleteButton.php index 00966848b9b3177db7df9b0e8c6605d4c9f35013..c2961ece3dd4b6938635711b7836721cc243886e 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/DeleteButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/DeleteButton.php @@ -6,7 +6,7 @@ namespace Magento\Customer\Block\Adminhtml\Edit; use Magento\Customer\Api\AccountManagementInterface; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class DeleteButton diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/InvalidateTokenButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/InvalidateTokenButton.php index 7b02478d44516a095d203c1b5a31f6a73a1952bc..a3744a1e8b2c3d08dc3e5729edd0dc849401b84a 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/InvalidateTokenButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/InvalidateTokenButton.php @@ -5,7 +5,7 @@ */ namespace Magento\Customer\Block\Adminhtml\Edit; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class InvalidateTokenButton diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/OrderButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/OrderButton.php index 4b402caf146e2112786a254f797cb3ecd1341be2..0edfd379f6517bb9a979c157ca530f3118119084 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/OrderButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/OrderButton.php @@ -5,11 +5,10 @@ */ namespace Magento\Customer\Block\Adminhtml\Edit; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class OrderButton - * @package Magento\Customer\Block\Adminhtml\Edit */ class OrderButton extends GenericButton implements ButtonProviderInterface { @@ -42,7 +41,7 @@ class OrderButton extends GenericButton implements ButtonProviderInterface if ($customerId && $this->authorization->isAllowed('Magento_Sales::create')) { $data = [ 'label' => __('Create Order'), - 'on_click' => 'setLocation(\'' . $this->getCreateOrderUrl() . '\')', + 'on_click' => sprintf("location.href = '%s';", $this->getCreateOrderUrl()), 'class' => 'add', 'sort_order' => 40, ]; diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetButton.php index 81e2d5845910886742c0f0f85d26c4b6bb9cbf18..8581974c55b8d8472502b5552d7562d4e9ee96ec 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetButton.php @@ -5,11 +5,10 @@ */ namespace Magento\Customer\Block\Adminhtml\Edit; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class ResetButton - * @package Magento\Customer\Block\Adminhtml\Edit */ class ResetButton implements ButtonProviderInterface { @@ -21,7 +20,7 @@ class ResetButton implements ButtonProviderInterface return [ 'label' => __('Reset'), 'class' => 'reset', - 'on_click' => 'setLocation(window.location.href)', + 'on_click' => 'location.reload();', 'sort_order' => 30 ]; } diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetPasswordButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetPasswordButton.php index ff377711a9b506dd5c6061f36a8151bf333dbd6a..f2894efd0bd0ba816b4d627a48b703948d0a355a 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetPasswordButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/ResetPasswordButton.php @@ -5,11 +5,10 @@ */ namespace Magento\Customer\Block\Adminhtml\Edit; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class ResetPasswordButton - * @package Magento\Customer\Block\Adminhtml\Edit */ class ResetPasswordButton extends GenericButton implements ButtonProviderInterface { @@ -24,7 +23,7 @@ class ResetPasswordButton extends GenericButton implements ButtonProviderInterfa $data = [ 'label' => __('Reset Password'), 'class' => 'reset reset-password', - 'on_click' => 'setLocation(\'' . $this->getResetPasswordUrl() . '\')', + 'on_click' => sprintf("location.href = '%s';", $this->getResetPasswordUrl()), 'sort_order' => 40, ]; } diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveAndContinueButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveAndContinueButton.php index f3113b1503ab1896f6bb82e030525640dea77a5c..44b9d328b252e848acfb58c6a8ecd4f37e35c1e1 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveAndContinueButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveAndContinueButton.php @@ -6,11 +6,10 @@ namespace Magento\Customer\Block\Adminhtml\Edit; use Magento\Customer\Api\AccountManagementInterface; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class SaveAndContinueButton - * @package Magento\Customer\Block\Adminhtml\Edit */ class SaveAndContinueButton extends GenericButton implements ButtonProviderInterface { diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveButton.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveButton.php index b52302c73c90a619723dd57cb8552cb555a892c5..33f0bdada2941a33f6a5e38b3ec6ad99a425c8a6 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveButton.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/SaveButton.php @@ -6,7 +6,7 @@ namespace Magento\Customer\Block\Adminhtml\Edit; use Magento\Customer\Api\AccountManagementInterface; -use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; /** * Class SaveButton diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php index 4a6743eddfabfa5ea5e4edc92c88aa13e8d40e7c..08919f7401d9007c97a89ad793161063ae4ca1cb 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php @@ -27,7 +27,7 @@ class Save extends \Magento\Customer\Controller\Adminhtml\Index protected function _extractCustomerData() { $customerData = []; - if ($this->getRequest()->getPost('account')) { + if ($this->getRequest()->getPost('customer')) { $serviceAttributes = [ CustomerInterface::DEFAULT_BILLING, CustomerInterface::DEFAULT_SHIPPING, @@ -40,7 +40,7 @@ class Save extends \Magento\Customer\Controller\Adminhtml\Index 'adminhtml_customer', \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, $serviceAttributes, - 'account' + 'customer' ); } @@ -113,7 +113,7 @@ class Save extends \Magento\Customer\Controller\Adminhtml\Index $extractedCustomerData[CustomerInterface::DEFAULT_BILLING] = null; $extractedCustomerData[CustomerInterface::DEFAULT_SHIPPING] = null; foreach ($addressIdList as $addressId) { - $scope = sprintf('account/customer_address/%s', $addressId); + $scope = sprintf('address/%s', $addressId); $addressData = $this->_extractData( $this->getRequest(), 'adminhtml_customer_address', @@ -151,10 +151,9 @@ class Save extends \Magento\Customer\Controller\Adminhtml\Index */ protected function _extractCustomerAddressData(array & $extractedCustomerData) { - $customerData = $this->getRequest()->getPost('account'); - $addresses = isset($customerData['customer_address']) ? $customerData['customer_address'] : []; + $addresses = $this->getRequest()->getPost('address'); $result = []; - if ($addresses) { + if (is_array($addresses)) { if (isset($addresses['_template_'])) { unset($addresses['_template_']); } @@ -177,8 +176,10 @@ class Save extends \Magento\Customer\Controller\Adminhtml\Index public function execute() { $returnToEdit = false; - $customerId = (int)$this->getRequest()->getParam('id'); $originalRequestData = $this->getRequest()->getPostValue(); + $customerId = isset($originalRequestData['customer']['entity_id']) + ? $originalRequestData['customer']['entity_id'] + : null; if ($originalRequestData) { try { // optional fields might be set in request for future processing by observers in other modules diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php index 3986551d78389058e3f503511c7bf9d621ee66f5..b701d653dc030d2436527e924c5761f369e9da99 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php @@ -37,7 +37,7 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index ); $customerForm->setInvisibleIgnored(true); - $data = $customerForm->extractData($this->getRequest(), 'account'); + $data = $customerForm->extractData($this->getRequest(), 'customer'); if ($customer->getWebsiteId()) { unset($data['website_id']); @@ -74,8 +74,7 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index */ protected function _validateCustomerAddress($response) { - $customerData = $this->getRequest()->getParam('account'); - $addresses = isset($customerData['customer_address']) ? $customerData['customer_address'] : []; + $addresses = $this->getRequest()->getPost('address'); if (!is_array($addresses)) { return; } @@ -86,7 +85,7 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index $addressForm = $this->_formFactory->create('customer_address', 'adminhtml_customer_address'); - $requestScope = sprintf('account/customer_address/%s', $index); + $requestScope = sprintf('address/%s', $index); $formData = $addressForm->extractData($this->getRequest(), $requestScope); $errors = $addressForm->validateData($formData); diff --git a/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php b/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php index 7e187a71e5c08bdad11cf84b9cfdc3c9ca85632c..b25f4c6d0b3a3cb83b3693f1d2d7c08fb4859247 100644 --- a/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php +++ b/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php @@ -5,6 +5,8 @@ */ namespace Magento\Customer\Model\Config\Backend\Address; +use Magento\Framework\App\Config\ScopeConfigInterface; + /** * Line count config model for customer address street attribute * @@ -64,7 +66,7 @@ class Street extends \Magento\Framework\App\Config\Value } break; - case \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT: + case ScopeConfigInterface::SCOPE_TYPE_DEFAULT: $attribute->setData('multiline_count', $value); break; } diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index d6792e7d47c2a33d77b8b6991754a7dad31c3e56..776c8e74e1ace9aa8cc4205174c6fb0977032368 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -12,6 +12,7 @@ use Magento\Customer\Model\Resource\Address\CollectionFactory; use Magento\Customer\Model\Resource\Customer as ResourceCustomer; use Magento\Customer\Api\Data\CustomerInterfaceFactory; use Magento\Customer\Model\Data\Customer as CustomerData; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Framework\Exception\EmailNotConfirmedException; use Magento\Framework\Exception\InvalidEmailOrPasswordException; @@ -1034,6 +1035,12 @@ class Customer extends \Magento\Framework\Model\AbstractModel $errors[] = __('Gender is required.'); } + $transport = new \Magento\Framework\Object( + ['errors' => $errors] + ); + $this->_eventManager->dispatch('customer_validate', ['customer' => $this, 'transport' => $transport]); + $errors = $transport->getErrors(); + if (empty($errors)) { return true; } @@ -1304,7 +1311,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel { return (int)$this->_scopeConfig->getValue( self::XML_PATH_CUSTOMER_RESET_PASSWORD_LINK_EXPIRATION_PERIOD, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ); } diff --git a/app/code/Magento/Customer/Model/Customer/DataProvider.php b/app/code/Magento/Customer/Model/Customer/DataProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..8597c0da84a866ac3cd2be1812044273e782ec77 --- /dev/null +++ b/app/code/Magento/Customer/Model/Customer/DataProvider.php @@ -0,0 +1,373 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Customer\Model\Customer; + +use Magento\Eav\Model\Config; +use Magento\Eav\Model\Entity\Type; +use Magento\Customer\Model\Address; +use Magento\Customer\Model\Customer; +use Magento\Ui\DataProvider\EavValidationRul; +use Magento\Customer\Model\Resource\Customer\Collection; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; +use Magento\Customer\Model\Resource\Customer\CollectionFactory as CustomerCollectionFactory; + +/** + * Class DataProvider + */ +class DataProvider implements DataProviderInterface +{ + /** + * @var string + */ + protected $primaryFieldName; + + /** + * @var string + */ + protected $requestFieldName; + + /** + * @var Collection + */ + protected $collection; + + /** + * @var Config + */ + protected $eavConfig; + + /** + * @var array + */ + protected $meta = []; + + /** + * Provider configuration data + * + * @var array + */ + protected $data = []; + + /** + * @var array + */ + protected $loadedData; + + /** + * EAV attribute properties to fetch from meta storage + * @var array + */ + protected $metaProperties = [ + 'dataType' => 'frontend_input', + 'visible' => 'is_visible', + 'required' => 'is_required', + 'label' => 'frontend_label', + 'sortOrder' => 'sort_order', + 'notice' => 'note', + 'default' => 'default_value', + 'size' => 'scope_multiline_count' + ]; + + /** + * Form element mapping + * + * @var array + */ + protected $formElement = [ + 'text' => 'input', + 'hidden' => 'input', + 'boolean' => 'checkbox', + ]; + + /** + * @var EavValidationRul + */ + protected $eavValidationRul; + + /** + * Constructor + * + * @param string $primaryFieldName + * @param string $requestFieldName + * @param EavValidationRul $eavValidationRul + * @param CustomerCollectionFactory $customerCollectionFactory + * @param Config $eavConfig + * @param array $meta + * @param array $data + */ + public function __construct( + $primaryFieldName, + $requestFieldName, + EavValidationRul $eavValidationRul, + CustomerCollectionFactory $customerCollectionFactory, + Config $eavConfig, + array $meta = [], + array $data = [] + ) { + $this->primaryFieldName = $primaryFieldName; + $this->requestFieldName = $requestFieldName; + $this->eavValidationRul = $eavValidationRul; + $this->collection = $customerCollectionFactory->create(); + $this->collection->addAttributeToSelect('*'); + $this->eavConfig = $eavConfig; + $this->meta = $meta; + $this->meta['customer']['fields'] = $this->getAttributesMeta( + $this->eavConfig->getEntityType('customer') + ); + $this->meta['address']['fields'] = $this->getAttributesMeta( + $this->eavConfig->getEntityType('customer_address') + ); + $this->data = $data; + } + + /** + * Get meta data + * + * @return array + */ + public function getMeta() + { + return $this->meta; + } + + /** + * Get field meta info + * + * @param string $fieldSetName + * @param string $fieldName + * @return array + */ + public function getFieldMetaInfo($fieldSetName, $fieldName) + { + return isset($this->meta[$fieldSetName]['fields'][$fieldName]) + ? $this->meta[$fieldSetName]['fields'][$fieldName] + : []; + } + + /** + * Get config data + * + * @return mixed + */ + public function getConfigData() + { + return isset($this->data['config']) ? $this->data['config'] : []; + } + + /** + * Set data + * + * @param mixed $config + * @return void + */ + public function setConfigData($config) + { + $this->data['config'] = $config; + } + + /** + * Get data + * + * @return array + */ + public function getData() + { + if (isset($this->loadedData)) { + return $this->loadedData; + } + + $items = $this->collection->getItems(); + /** @var Customer $customer */ + foreach ($items as $customer) { + $result['customer'] = $customer->getData(); + + $addresses = []; + /** @var Address $address */ + foreach ($customer->getAddresses() as $address) { + $addressId = $address->getId(); + $address->load($addressId); + $addresses[$addressId] = $address->getData(); + $this->prepareAddressData($addressId, $addresses, $result['customer']); + } + if (!empty($addresses)) { + $result['address'] = $addresses; + } + + $this->loadedData[$customer->getId()] = $result; + } + + return $this->loadedData; + } + + /** + * Get field name in request + * + * @return string + */ + public function getRequestFieldName() + { + return $this->requestFieldName; + } + + /** + * Get primary field name + * + * @return string + */ + public function getPrimaryFieldName() + { + return $this->primaryFieldName; + } + + /** + * @inheritdoc + */ + public function addFilter($field, $condition = null) + { + $this->collection->addFieldToFilter($field, $condition); + } + + /** + * Add field to select + * + * @param string|array $field + * @param string|null $alias + * @return void + */ + public function addField($field, $alias = null) + { + $this->collection->addAttributeToSelect($field); + } + + /** + * self::setOrder() alias + * + * @param string $field + * @param string $direction + * @return void + */ + public function addOrder($field, $direction) + { + $this->collection->addOrder($field, $direction); + } + + /** + * Set Query limit + * + * @param int $offset + * @param int $size + * @return void + */ + public function setLimit($offset, $size) + { + $this->collection->setPageSize($size); + $this->collection->setCurPage($offset); + } + + /** + * Removes field from select + * + * @param string|null $field + * @param bool $isAlias Alias identifier + * @return void + */ + public function removeField($field, $isAlias = false) + { + $this->collection->removeAttributeToSelect($field); + } + + /** + * Removes all fields from select + * + * @return void + */ + public function removeAllFields() + { + $this->collection->removeAttributeToSelect(); + } + + /** + * Retrieve count of loaded items + * + * @return int + */ + public function count() + { + return $this->collection->count(); + } + + /** + * Get fields meta info + * + * @param string $fieldSetName + * @return array + */ + public function getFieldsMetaInfo($fieldSetName) + { + return isset($this->meta[$fieldSetName]['fields']) ? $this->meta[$fieldSetName]['fields'] : []; + } + + /** + * Get attributes meta + * + * @param Type $entityType + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function getAttributesMeta(Type $entityType) + { + $meta = []; + $attributes = $entityType->getAttributeCollection(); + /* @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */ + foreach ($attributes as $attribute) { + $code = $attribute->getAttributeCode(); + // use getDataUsingMethod, since some getters are defined and apply additional processing of returning value + foreach ($this->metaProperties as $metaName => $origName) { + $value = $attribute->getDataUsingMethod($origName); + $meta[$code][$metaName] = $value; + if ('frontend_input' === $origName) { + $meta[$code]['formElement'] = isset($this->formElement[$value]) + ? $this->formElement[$value] + : $value; + } + if ($attribute->usesSource()) { + $meta[$code]['options'] = $attribute->getSource()->getAllOptions(); + } + } + + $rules = $this->eavValidationRul->build($attribute, $meta[$code]); + if (!empty($rules)) { + $meta[$code]['validation'] = $rules; + } + } + return $meta; + } + + /** + * Prepare address data + * + * @param int $addressId + * @param array $addresses + * @param array $customer + * @return void + */ + protected function prepareAddressData($addressId, array &$addresses, array $customer) + { + if (isset($customer['default_billing']) + && $addressId == $customer['default_billing'] + ) { + $addresses[$addressId]['default_billing'] = $customer['default_billing']; + } + if (isset($customer['default_shipping']) + && $addressId == $customer['default_shipping'] + ) { + $addresses[$addressId]['default_shipping'] = $customer['default_shipping']; + } + if (isset($addresses[$addressId]['street'])) { + $addresses[$addressId]['street'] = explode("\n", $addresses[$addressId]['street']); + } + } +} diff --git a/app/code/Magento/Customer/Model/Resource/Address.php b/app/code/Magento/Customer/Model/Resource/Address.php index 57a5c1cbcf3d9c28e975a999395d5ffd18600696..3b6ae0a28c8f9e812e762b72dbfe45d35681ebe9 100644 --- a/app/code/Magento/Customer/Model/Resource/Address.php +++ b/app/code/Magento/Customer/Model/Resource/Address.php @@ -45,13 +45,22 @@ class Address extends \Magento\Eav\Model\Entity\AbstractEntity */ protected function _construct() { - $resource = $this->_resource; - $this->setType( - 'customer_address' - )->setConnection( - $resource->getConnection('customer_read'), - $resource->getConnection('customer_write') - ); + $this->_read = 'customer_read'; + $this->_write = 'customer_write'; + } + + /** + * Getter and lazy loader for _type + * + * @throws \Magento\Framework\Exception\LocalizedException + * @return \Magento\Eav\Model\Entity\Type + */ + public function getEntityType() + { + if (empty($this->_type)) { + $this->setType('customer_address'); + } + return parent::getEntityType(); } /** diff --git a/app/code/Magento/Customer/Model/Session.php b/app/code/Magento/Customer/Model/Session.php index c01cd99d642cf7cb72c963fc20513f2e8e525235..4212be78b59114439b049203b03eca3a488991e4 100644 --- a/app/code/Magento/Customer/Model/Session.php +++ b/app/code/Magento/Customer/Model/Session.php @@ -102,6 +102,7 @@ class Session extends \Magento\Framework\Session\SessionManager * @param \Magento\Framework\Session\StorageInterface $storage * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory + * @param \Magento\Framework\App\State $appState * @param Share $configShare * @param \Magento\Framework\Url\Helper\Data $coreUrl * @param \Magento\Customer\Model\Url $customerUrl @@ -113,6 +114,7 @@ class Session extends \Magento\Framework\Session\SessionManager * @param \Magento\Framework\App\Http\Context $httpContext * @param CustomerRepositoryInterface $customerRepository * @param GroupManagementInterface $groupManagement + * @throws \Magento\Framework\Exception\SessionException * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -124,6 +126,7 @@ class Session extends \Magento\Framework\Session\SessionManager \Magento\Framework\Session\StorageInterface $storage, \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory, + \Magento\Framework\App\State $appState, Config\Share $configShare, \Magento\Framework\Url\Helper\Data $coreUrl, \Magento\Customer\Model\Url $customerUrl, @@ -154,9 +157,9 @@ class Session extends \Magento\Framework\Session\SessionManager $validator, $storage, $cookieManager, - $cookieMetadataFactory + $cookieMetadataFactory, + $appState ); - $this->start(); $this->groupManagement = $groupManagement; $this->_eventManager->dispatch('customer_session_init', ['customer_session' => $this]); } diff --git a/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php b/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php index 5d1e91708b4fcd6da306011c551415bf3586d66a..834c64df6701f19605ccd05fb8298d1def87fa4a 100644 --- a/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php +++ b/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php @@ -10,6 +10,7 @@ namespace Magento\Customer\Test\Unit\Block\Widget; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Customer\Block\Widget\Dob; +use Magento\Framework\Locale\Resolver; class DobTest extends \PHPUnit_Framework_TestCase { @@ -69,7 +70,7 @@ class DobTest extends \PHPUnit_Framework_TestCase $localeResolver = $this->getMock('\Magento\Framework\Locale\ResolverInterface'); $localeResolver->expects($this->any()) ->method('getLocale') - ->willReturn(\Magento\Framework\Locale\ResolverInterface::DEFAULT_LOCALE); + ->willReturn(Resolver::DEFAULT_LOCALE); $timezone = $objectManager->getObject( 'Magento\Framework\Stdlib\DateTime\Timezone', ['localeResolver' => $localeResolver] diff --git a/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php b/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php index fe17aa1aca70eb47723da99b6c9a8639944b76de..c15cf1596c8245fb30d8a79ba097923d545c26b0 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Resource/AddressTest.php @@ -18,6 +18,9 @@ class AddressTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Customer\Model\CustomerFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $customerFactory; + /** @var \Magento\Eav\Model\Entity\Type */ + protected $eavConfigType; + protected function setUp() { $this->addressResource = (new ObjectManagerHelper($this))->getObject( @@ -178,16 +181,16 @@ class AddressTest extends \PHPUnit_Framework_TestCase ) ); - $eavConfigType = $this->getMock( + $this->eavConfigType = $this->getMock( 'Magento\Eav\Model\Entity\Type', ['getEntityIdField', 'getId', 'getEntityTable', '__wakeup'], [], '', false ); - $eavConfigType->expects($this->any())->method('getEntityIdField')->willReturn(false); - $eavConfigType->expects($this->any())->method('getId')->willReturn(false); - $eavConfigType->expects($this->any())->method('getEntityTable')->willReturn('customer_address_entity'); + $this->eavConfigType->expects($this->any())->method('getEntityIdField')->willReturn(false); + $this->eavConfigType->expects($this->any())->method('getId')->willReturn(false); + $this->eavConfigType->expects($this->any())->method('getEntityTable')->willReturn('customer_address_entity'); $eavConfig = $this->getMock( 'Magento\Eav\Model\Config', @@ -199,10 +202,10 @@ class AddressTest extends \PHPUnit_Framework_TestCase $eavConfig->expects($this->any()) ->method('getEntityType') ->with('customer_address') - ->willReturn($eavConfigType); + ->willReturn($this->eavConfigType); $eavConfig->expects($this->any()) ->method('getEntityAttributeCodes') - ->with($eavConfigType) + ->with($this->eavConfigType) ->willReturn( [ 'entity_type_id', @@ -217,13 +220,13 @@ class AddressTest extends \PHPUnit_Framework_TestCase $eavConfig->expects($this->any()) ->method('getAttribute') ->willReturnMap([ - [$eavConfigType, 'entity_type_id', $attributeMock], - [$eavConfigType, 'attribute_set_id', $attributeMock], - [$eavConfigType, 'created_at', $attributeMock], - [$eavConfigType, 'updated_at', $attributeMock], - [$eavConfigType, 'parent_id', $attributeMock], - [$eavConfigType, 'increment_id', $attributeMock], - [$eavConfigType, 'entity_id', $attributeMock], + [$this->eavConfigType, 'entity_type_id', $attributeMock], + [$this->eavConfigType, 'attribute_set_id', $attributeMock], + [$this->eavConfigType, 'created_at', $attributeMock], + [$this->eavConfigType, 'updated_at', $attributeMock], + [$this->eavConfigType, 'parent_id', $attributeMock], + [$this->eavConfigType, 'increment_id', $attributeMock], + [$this->eavConfigType, 'entity_id', $attributeMock], ]); return $eavConfig; @@ -261,4 +264,9 @@ class AddressTest extends \PHPUnit_Framework_TestCase $this->customerFactory = $this->getMock('Magento\Customer\Model\CustomerFactory', ['create'], [], '', false); return $this->customerFactory; } + + public function testGetType() + { + $this->assertSame($this->eavConfigType, $this->addressResource->getEntityType()); + } } diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json index 340ab29eca160e1cca6c80f8426ea2ebe66261cb..0e4da26475620658642e2a1582cbe7391c7b2edc 100644 --- a/app/code/Magento/Customer/composer.json +++ b/app/code/Magento/Customer/composer.json @@ -3,33 +3,33 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-newsletter": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-wishlist": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-review": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-page-cache": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-authorization": "0.74.0-beta6", - "magento/module-integration": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/module-ui": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-newsletter": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-wishlist": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-review": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-page-cache": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-authorization": "0.74.0-beta7", + "magento/module-integration": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/module-ui": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta6" + "magento/module-cookie": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Customer/etc/data_source/customer.xml b/app/code/Magento/Customer/etc/data_source/customer.xml deleted file mode 100644 index 10fddb904a989f9f5a94fc1af7181458d65fd473..0000000000000000000000000000000000000000 --- a/app/code/Magento/Customer/etc/data_source/customer.xml +++ /dev/null @@ -1,62 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../app/code/Magento/Ui/etc/data_source.xsd"> - <dataSource - name="account" label="Account Information" - dataSet="Magento\Customer\Model\Resource\Customer\Collection"> - <fields entityType="customer"> - <field name="entity_id" dataType="text" visible="false"/> - <field name="default_billing" source="eav" dataType="boolean" visible="false"/> - <field name="default_shipping" source="eav" dataType="boolean" visible="false"/> - <field name="website_id" dataType="number" formElement="select" source="eav" label="Associate to Website"> - <constraints> - <validate name="required-entry"/> - </constraints> - <tooltip> - <link>http://www.magentocommerce.com/knowledge-base/entry/understanding-store-scopes</link> - <description>If your Magento site has multiple views, you can set the scope to apply to a specific view.</description> - </tooltip> - </field> - <field name="prefix" source="eav" dataType="text"/> - <field name="group_id" dataType="number" formElement="select" source="eav" label="Group" fieldGroup="group_id" /> - <field name="disable_auto_group_change" source="eav" dataType="boolean" formElement="checkbox" fieldGroup="group_id"/> - <field name="firstname" source="eav" dataType="text"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="middlename" source="eav" dataType="text"/> - <field name="lastname" source="eav" dataType="text"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="suffix" source="eav" dataType="text"/> - <field name="email" source="eav" formElement="email"> - <constraints> - <validate name="required-entry"/> - <validate name="validate-email"/> - </constraints> - </field> - <field name="dob" source="eav" dataType="text" label="Date Of Birth" formElement="date"/> - <field name="taxvat" source="eav" dataType="text" label="Tax VAT Number"/> - <field name="gender" source="eav" dataType="text" formElement="select"/> - <field name="sendemail" - dataType="boolean" - formElement="checkbox" - label="Welcome Email" - description="Send a Welcome email "/> - <field name="sendemail_store_id" - dataType="number" - formElement="select" - optionProvider="Magento\Store\Model\System\Store::getStoreValuesForForm" - label="Send From"/> - </fields> - </dataSource> -</config> \ No newline at end of file diff --git a/app/code/Magento/Customer/etc/data_source/customer_address.xml b/app/code/Magento/Customer/etc/data_source/customer_address.xml deleted file mode 100644 index e3e88b578a12604b97419639750b8317019d0e51..0000000000000000000000000000000000000000 --- a/app/code/Magento/Customer/etc/data_source/customer_address.xml +++ /dev/null @@ -1,89 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../app/code/Magento/Ui/etc/data_source.xsd"> - <dataSource name="customer_address" - label="Customer Address" - dataSet="Magento\Customer\Model\Resource\Address\Collection"> - <fields entityType="customer_address"> - <field name="parent_id" dataType="number" visible="false"/> - <field name="prefix" source="eav"/> - <field name="firstname" source="eav"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="middlename" source="eav"/> - <field name="lastname" source="eav"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="suffix" source="eav"/> - <field name="company" source="eav" label="Company"/> - <field name="street" dataType="text" formElement="input" size="2" source="eav"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="city" source="eav"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="country_id" source="eav" formElement="select"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="region_id" source="eav" formElement="select" customEntry="region"> - <constraints> - <validate name="required-entry"/> - <filter on="{parentScope}.country_id" by="country_id" /> - </constraints> - </field> - <field name="region" source="eav" formElement="input" visible="false"/> - - <field name="postcode" source="eav" formElement="post_code" > - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - - <field name="telephone" source="eav" label="Phone Number"> - <constraints> - <validate name="required-entry"/> - </constraints> - </field> - <field name="fax" source="eav" label="Fax"/> - <field name="vat_id" source="eav" label="VAT number"/> - <field name="default_billing" source="reference" dataType="boolean" formElement="checkbox" - displayArea="head" description="Default Billing Address" uniqueNs="default_billing" uniqueProp="value"> - <reference target="account" - referencedField="parent_id" - targetField="entity_id" - neededField="default_billing" - /> - </field> - <field name="default_shipping" source="reference" dataType="boolean" formElement="checkbox" - displayArea="head" description="Default Shipping Address" uniqueNs="default_shipping" uniqueProp="value"> - <reference target="account" - referencedField="parent_id" - targetField="entity_id" - neededField="default_shipping" - /> - </field> - </fields> - <references> - <reference target="account" - referencedField="parent_id" - targetField="entity_id" - /> - </references> - </dataSource> -</config> diff --git a/app/code/Magento/Customer/etc/data_source/customer_group.xml b/app/code/Magento/Customer/etc/data_source/customer_group.xml deleted file mode 100644 index 87da4cb4d717c8fc029e1f1331f4a80efffb7963..0000000000000000000000000000000000000000 --- a/app/code/Magento/Customer/etc/data_source/customer_group.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../app/code/Magento/Ui/etc/data_source.xsd"> - <dataSource name="customer_group" label="Customer Group" dataSet="Magento\Customer\Model\Resource\Group\Collection"> - <fields> - <field name="customer_group_id" dataType="number" visible="false"/> - <field name="customer_group_code" dataType="text"/> - </fields> - </dataSource> -</config> \ No newline at end of file diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_form.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_form.xml deleted file mode 100644 index 9893992bb265420ff38bc1b3dd18ccdacaa8b9b2..0000000000000000000000000000000000000000 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_form.xml +++ /dev/null @@ -1,72 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> - <body> - <referenceBlock name="form"> - <arguments> - <argument name="meta" xsi:type="array"> - <item name="defaults" xsi:type="array"> - <item name="visible" xsi:type="boolean">true</item> - </item> - </argument> - <argument name="label" xsi:type="string">Customer Information</argument> - <argument name="name" xsi:type="string">customer_form</argument> - <argument name="data_sources" xsi:type="array"> - <item name="customer_info" xsi:type="array"> - <item name="name" xsi:type="string">account</item> - <item name="submit_url" xsi:type="url" path="customer/index/save"> - <param name="_current">1</param> - <param name="back"></param> - </item> - <item name="validate_url" xsi:type="url" path="customer/index/validate"> - <param name="_current">1</param> - <param name="back"></param> - </item> - </item> - </argument> - <argument name="layout" xsi:type="array"> - <item name="type" xsi:type="string">tabs</item> - <item name="configuration" xsi:type="array"> - <item name="tabs_container_name" xsi:type="string">left</item> - <item name="areas" xsi:type="array"> - <item name="general" xsi:type="array"> - <item name="index" xsi:type="string">account_info</item> - <item name="type" xsi:type="string">fieldset</item> - <item name="label" xsi:type="string" translate="true">Customer Info</item> - <item name="collapsible" xsi:type="boolean">true</item> - <item name="ajax" xsi:type="boolean">true</item> - </item> - <item name="customer_address" xsi:type="array"> - <item name="index" xsi:type="string">customer_address</item> - <item name="type" xsi:type="string">tab</item> - <item name="label" xsi:type="string" translate="true">Customer Address</item> - </item> - </item> - </item> - </argument> - <argument name="buttons" xsi:type="array"> - <item name="back" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\BackButton</item> - <item name="delete" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\DeleteButton</item> - <item name="invalidateToken" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\InvalidateTokenButton</item> - <item name="resetPassword" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\ResetPasswordButton</item> - <item name="order" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\OrderButton</item> - <item name="reset" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\ResetButton</item> - <item name="save" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\SaveButton</item> - <item name="save_and_continue" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\SaveAndContinueButton</item> - </argument> - </arguments> - <block class="Magento\Customer\Block\Adminhtml\Edit\Tab\View" name="customer_edit_tab_view" template="tab/view.phtml"> - <arguments> - <argument name="tab_label" xsi:type="string">Customer View</argument> - <argument name="sort_order" xsi:type="number">10</argument> - </arguments> - <block class="Magento\Customer\Block\Adminhtml\Edit\Tab\View\PersonalInfo" name="personal_info" template="tab/view/personal_info.phtml"/> - </block> - </referenceBlock> - </body> -</page> diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml index 12fa054b6398b5714ecedc796294822336b22b03..4d3ff76ccb80b348cf0a9bee817580682f7dd61b 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml @@ -5,11 +5,21 @@ * See COPYING.txt for license details. */ --> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" + xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> <referenceContainer name="content"> - <ui_component name="customer_form" component="form" /> + <referenceBlock name="customer_form"> + <block class="Magento\Customer\Block\Adminhtml\Edit\Tab\View" name="customer_edit_tab_view" template="tab/view.phtml"> + <arguments> + <argument name="tab_label" xsi:type="string">Customer View</argument> + <argument name="sort_order" xsi:type="number">10</argument> + </arguments> + <block class="Magento\Customer\Block\Adminhtml\Edit\Tab\View\PersonalInfo" name="personal_info" template="tab/view/personal_info.phtml"/> + </block> + </referenceBlock> + <uiComponent name="customer_form"/> </referenceContainer> </body> </page> diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml new file mode 100644 index 0000000000000000000000000000000000000000..eb6199714da3274dc2302072d7cf26a60ed2088a --- /dev/null +++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml @@ -0,0 +1,553 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Ui/etc/ui_configuration.xsd"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="provider" xsi:type="string">customer_form.customer_form_data_source</item> + </item> + <item name="deps" xsi:type="string">customer_form.customer_form_data_source</item> + </item> + <item name="label" xsi:type="string" translate="true">Customer Information</item> + <item name="layout" xsi:type="array"> + <item name="type" xsi:type="string">tabs</item> + <item name="navContainerName" xsi:type="string">left</item> + </item> + <item name="buttons" xsi:type="array"> + <item name="back" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\BackButton</item> + <item name="delete" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\DeleteButton</item> + <item name="invalidateToken" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\InvalidateTokenButton</item> + <item name="resetPassword" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\ResetPasswordButton</item> + <item name="order" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\OrderButton</item> + <item name="reset" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\ResetButton</item> + <item name="save" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\SaveButton</item> + <item name="save_and_continue" xsi:type="string">Magento\Customer\Block\Adminhtml\Edit\SaveAndContinueButton</item> + </item> + </argument> + <dataSource name="customer_form_data_source"> + <argument name="dataProvider" xsi:type="configurableObject"> + <argument name="class" xsi:type="string">Magento\Customer\Model\Customer\DataProvider</argument> + <argument name="primaryFieldName" xsi:type="string">entity_id</argument> + <argument name="requestFieldName" xsi:type="string">id</argument> + <argument name="meta" xsi:type="array"> + <item name="customer" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Account Information</item> + </item> + </item> + <item name="address" xsi:type="array"> + <item name="is_collection" xsi:type="boolean">true</item> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Addresses</item> + </item> + </item> + </argument> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> + </item> + <item name="config" xsi:type="array"> + <item name="submit_url" xsi:type="string">customer/index/save</item> + <item name="validate_url" xsi:type="string">customer/index/validate</item> + </item> + </argument> + </argument> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/provider</item> + </item> + </argument> + </dataSource> + <fieldset name="customer"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Account Information</item> + </item> + </argument> + <field name="entity_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">false</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="created_in"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">false</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="default_billing"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">false</item> + <item name="dataType" xsi:type="string">boolean</item> + <item name="formElement" xsi:type="string">checkbox</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="default_shipping"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">false</item> + <item name="dataType" xsi:type="string">boolean</item> + <item name="formElement" xsi:type="string">checkbox</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="website_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">number</item> + <item name="formElement" xsi:type="string">select</item> + <item name="source" xsi:type="string">customer</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + <item name="tooltip" xsi:type="array"> + <item name="link" xsi:type="string">http://www.magentocommerce.com/knowledge-base/entry/understanding-store-scopes</item> + <item name="description" xsi:type="string">If your Magento site has multiple views, you can set the scope to apply to a specific view.</item> + </item> + </item> + </argument> + </field> + <field name="prefix"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <container name="container_group"> + <argument name="data" xsi:type="array"> + <item name="type" xsi:type="string">group</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/components/group</item> + </item> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Group</item> + <item name="required" xsi:type="boolean">true</item> + <item name="dataScope" xsi:type="boolean">false</item> + <item name="sortOrder" xsi:type="number">20</item> + </item> + </argument> + <field name="group_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="fieldGroup" xsi:type="string">group_id</item> + <item name="dataType" xsi:type="string">number</item> + <item name="formElement" xsi:type="string">select</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="disable_auto_group_change"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="fieldGroup" xsi:type="string">group_id</item> + <item name="dataType" xsi:type="string">boolean</item> + <item name="formElement" xsi:type="string">checkbox</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + </container> + <field name="firstname"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="middlename"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="lastname"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="suffix"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="email"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="extends" xsi:type="string">input</item> + </item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">email</item> + <item name="source" xsi:type="string">customer</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + <item name="validate-email" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="dob"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">date</item> + <item name="source" xsi:type="string">customer</item> + <item name="validation" xsi:type="array"> + <item name="validate-date" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="taxvat"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="gender"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">select</item> + <item name="source" xsi:type="string">customer</item> + </item> + </argument> + </field> + <field name="sendemail_store_id"> + <argument name="data" xsi:type="array"> + <item name="options" xsi:type="object">Magento\Store\Model\System\Store</item> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string">Send From</item> + <item name="dataType" xsi:type="string">number</item> + <item name="formElement" xsi:type="string">select</item> + </item> + </argument> + </field> + <field name="sendemail"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string">Welcome Email</item> + <item name="description" xsi:type="string">Send a Welcome email</item> + <item name="dataType" xsi:type="string">boolean</item> + <item name="formElement" xsi:type="string">checkbox</item> + </item> + </argument> + </field> + </fieldset> + <fieldset name="address"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="is_collection" xsi:type="boolean">true</item> + <item name="label" xsi:type="string" translate="true">Addresses</item> + <item name="removeMessage" xsi:type="string" translate="true">Are you sure you want to delete this item?</item> + </item> + </argument> + <field name="parent_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">false</item> + <item name="dataType" xsi:type="string">number</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + </item> + </argument> + </field> + <field name="prefix"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + </item> + </argument> + </field> + <field name="firstname"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="source" xsi:type="string">address</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="middlename"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + </item> + </argument> + </field> + <field name="lastname"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="suffix"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">true</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="sortOrder" xsi:type="string">43</item> + </item> + </argument> + </field> + <field name="company"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="sortOrder" xsi:type="string">44</item> + <item name="validation" xsi:type="array"> + <item name="min_text_length" xsi:type="number">0</item> + </item> + </item> + </argument> + </field> + <container name="street_container"> + <argument name="data" xsi:type="array"> + <item name="type" xsi:type="string">group</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/components/group</item> + </item> + <item name="config" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Street Address</item> + <item name="required" xsi:type="boolean">true</item> + <item name="dataScope" xsi:type="string">street</item> + <item name="sortOrder" xsi:type="string">45</item> + </item> + </argument> + <field name="street"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">0</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="street_second"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataScope" xsi:type="string">1</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + </item> + </argument> + </field> + </container> + <field name="city"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="country_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">select</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="country_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">select</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="region"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="visible" xsi:type="boolean">false</item> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + </item> + </argument> + </field> + <field name="region_id"> + <argument name="data" xsi:type="array"> + <item name="customEntry" xsi:type="string">region</item> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">select</item> + <item name="source" xsi:type="string">address</item> + <item name="customEntry" xsi:type="string">region</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + <item name="filterBy" xsi:type="array"> + <item name="target" xsi:type="string"><![CDATA[<%= provider %>:<%= parentScope %>.country_id]]></item> + <item name="field" xsi:type="string">country_id</item> + </item> + </item> + </argument> + </field> + <field name="postcode"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="telephone"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="boolean">true</item> + </item> + </item> + </argument> + </field> + <field name="fax"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + <item name="validation" xsi:type="array"> + <item name="min_text_length" xsi:type="number">0</item> + </item> + </item> + </argument> + </field> + <field name="vat_id"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">text</item> + <item name="formElement" xsi:type="string">input</item> + <item name="source" xsi:type="string">address</item> + </item> + </argument> + </field> + <field name="default_billing"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">boolean</item> + <item name="formElement" xsi:type="string">checkbox</item> + <item name="displayArea" xsi:type="string">head</item> + <item name="uniqueNs" xsi:type="string">default_billing</item> + <item name="uniqueProp" xsi:type="string">value</item> + <item name="description" xsi:type="string" translate="true">Default Billing Address</item> + <item name="source" xsi:type="array"> + <item name="target" xsi:type="string">customer</item> + <item name="targetField" xsi:type="string">default_billing</item> + <item name="referencedField" xsi:type="string">entity_id</item> + </item> + </item> + </argument> + </field> + <field name="default_shipping"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="dataType" xsi:type="string">boolean</item> + <item name="formElement" xsi:type="string">checkbox</item> + <item name="displayArea" xsi:type="string">head</item> + <item name="uniqueNs" xsi:type="string">default_shipping</item> + <item name="uniqueProp" xsi:type="string">value</item> + <item name="description" xsi:type="string" translate="true">Default Shipping Address</item> + <item name="source" xsi:type="array"> + <item name="target" xsi:type="string">customer</item> + <item name="targetField" xsi:type="string">default_shipping</item> + <item name="referencedField" xsi:type="string">entity_id</item> + </item> + </item> + </argument> + </field> + </fieldset> +</form> diff --git a/app/code/Magento/CustomerImportExport/composer.json b/app/code/Magento/CustomerImportExport/composer.json index 3635354b9f3c6e0593281f1465051226cfc8c355..1541d6e931b963ebbe66888254d08f6022586430 100644 --- a/app/code/Magento/CustomerImportExport/composer.json +++ b/app/code/Magento/CustomerImportExport/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-import-export": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-import-export": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/DesignEditor/Model/Url/NavigationMode.php b/app/code/Magento/DesignEditor/Model/Url/NavigationMode.php index af413fcd477b0b044e36d1bc9ed4bfc3c6637eb5..cb54368e519392d63b842cd6227cce1644e51c7d 100644 --- a/app/code/Magento/DesignEditor/Model/Url/NavigationMode.php +++ b/app/code/Magento/DesignEditor/Model/Url/NavigationMode.php @@ -38,7 +38,7 @@ class NavigationMode extends \Magento\Framework\Url * @param \Magento\Framework\Url\ScopeResolverInterface $scopeResolver * @param \Magento\Framework\Session\Generic $session * @param \Magento\Framework\Session\SidResolverInterface $sidResolver - * @param \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolver + * @param \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory * @param \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param string $scopeType @@ -53,7 +53,7 @@ class NavigationMode extends \Magento\Framework\Url \Magento\Framework\Url\ScopeResolverInterface $scopeResolver, \Magento\Framework\Session\Generic $session, \Magento\Framework\Session\SidResolverInterface $sidResolver, - \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolver, + \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory, \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, $scopeType, @@ -75,7 +75,7 @@ class NavigationMode extends \Magento\Framework\Url $scopeResolver, $session, $sidResolver, - $routeParamsResolver, + $routeParamsResolverFactory, $queryParamsResolver, $scopeConfig, $scopeType, diff --git a/app/code/Magento/DesignEditor/Test/Unit/Model/Url/NavigationModeTest.php b/app/code/Magento/DesignEditor/Test/Unit/Model/Url/NavigationModeTest.php index e6de82bcf54ee3798e263bafb0d3a5f77c5e1435..e4ee8ff76365954f2ec2b404f72515d4c2cc3249 100644 --- a/app/code/Magento/DesignEditor/Test/Unit/Model/Url/NavigationModeTest.php +++ b/app/code/Magento/DesignEditor/Test/Unit/Model/Url/NavigationModeTest.php @@ -90,7 +90,7 @@ class NavigationModeTest extends \PHPUnit_Framework_TestCase [ 'helper' => $this->_designHelperMock, 'data' => $this->_testData, - 'routeParamsResolver' => $this->_routeParamsMock, + 'routeParamsResolverFactory' => $this->_routeParamsMock, 'scopeResolver' => $this->_scopeResolverMock ] ); diff --git a/app/code/Magento/DesignEditor/composer.json b/app/code/Magento/DesignEditor/composer.json index 7a24e23445b99be4268f881b05eff8013e9553da..f9d3156293edff7b668fddde96bc2c1b26871f33 100644 --- a/app/code/Magento/DesignEditor/composer.json +++ b/app/code/Magento/DesignEditor/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-translation": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-translation": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Developer/composer.json b/app/code/Magento/Developer/composer.json index 2acb479e5e7da4b25ea3e78b4269be86c45fa06c..dfe90bb1778175658e44a84c52ce21fc9243573a 100644 --- a/app/code/Magento/Developer/composer.json +++ b/app/code/Magento/Developer/composer.json @@ -3,12 +3,12 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Developer/etc/adminhtml/system.xml b/app/code/Magento/Developer/etc/adminhtml/system.xml index f858f6b51bc275787d5b476b42a1a3f62277ec11..13ec5c3a13106fc5820440bb0b7754e6404a5074 100644 --- a/app/code/Magento/Developer/etc/adminhtml/system.xml +++ b/app/code/Magento/Developer/etc/adminhtml/system.xml @@ -9,7 +9,7 @@ <section id="dev" translate="label"> <group id="front_end_development_workflow" translate="label" type="text" sortOrder="8" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Front-end development workflow</label> - <field id="type" translate="label comment" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1"> + <field id="type" translate="label comment" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Workflow type</label> <comment>Not available in production mode</comment> <source_model>Magento\Developer\Model\Config\Source\WorkflowType</source_model> diff --git a/app/code/Magento/Dhl/composer.json b/app/code/Magento/Dhl/composer.json index 9523a52d2f19d36247e9a99814c24cf43e8ee2a5..41241d5133de99d58082d16c854e2adb73acab39 100644 --- a/app/code/Magento/Dhl/composer.json +++ b/app/code/Magento/Dhl/composer.json @@ -3,22 +3,22 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Directory/Model/Currency.php b/app/code/Magento/Directory/Model/Currency.php index 9e7d2b9abef186b2f221c94c7ef61007534c81eb..31ab3bf266dd24b8fb1b657731f5b8bcf2c1bda4 100644 --- a/app/code/Magento/Directory/Model/Currency.php +++ b/app/code/Magento/Directory/Model/Currency.php @@ -311,6 +311,16 @@ class Currency extends \Magento\Framework\Model\AbstractModel return $this->_localeCurrency->getCurrency($this->getCode())->toCurrency($price, $options); } + /** + * Return currency symbol for current locale and currency code + * + * @return string + */ + public function getCurrencySymbol() + { + return $this->_localeCurrency->getCurrency($this->getCode())->getSymbol(); + } + /** * @return string */ diff --git a/app/code/Magento/Directory/Model/PriceCurrency.php b/app/code/Magento/Directory/Model/PriceCurrency.php index 3aa697742a41687cf66d0e78517afd3549aaac1c..9cf7dabd2de746d5193abe8bbf7b1c1f5662e550 100644 --- a/app/code/Magento/Directory/Model/PriceCurrency.php +++ b/app/code/Magento/Directory/Model/PriceCurrency.php @@ -117,6 +117,16 @@ class PriceCurrency implements \Magento\Framework\Pricing\PriceCurrencyInterface return $currentCurrency; } + /** + * @param null|string|bool|int|\Magento\Framework\App\ScopeInterface $scope + * @param \Magento\Framework\Model\AbstractModel|string|null $currency + * @return string + */ + public function getCurrencySymbol($scope = null, $currency = null) + { + return $this->getCurrency($scope, $currency)->getCurrencySymbol(); + } + /** * Get store model * diff --git a/app/code/Magento/Directory/Test/Unit/Model/CurrencyTest.php b/app/code/Magento/Directory/Test/Unit/Model/CurrencyTest.php new file mode 100644 index 0000000000000000000000000000000000000000..33a312880adc33b16f3c0f2327573b2f08d1ae32 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Model/CurrencyTest.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Directory\Test\Unit\Model; + +use Magento\Directory\Model\Currency; + +class CurrencyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Currency + */ + protected $currency; + + protected $currencyCode = 'USD'; + + /** + * @var \Magento\Framework\Locale\CurrencyInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $localeCurrencyMock; + + public function setUp() + { + $this->localeCurrencyMock = $this->getMock('\Magento\Framework\Locale\CurrencyInterface'); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->currency = $objectManager->getObject('Magento\Directory\Model\Currency', [ + 'localeCurrency' => $this->localeCurrencyMock, + 'data' => [ + 'currency_code' => $this->currencyCode, + ] + ]); + } + + public function testGetCurrencySymbol() + { + $currencySymbol = '$'; + + $currencyMock = $this->getMockBuilder('\Magento\Framework\Currency') + ->disableOriginalConstructor() + ->getMock(); + $currencyMock->expects($this->once()) + ->method('getSymbol') + ->willReturn($currencySymbol); + + $this->localeCurrencyMock->expects($this->once()) + ->method('getCurrency') + ->with($this->currencyCode) + ->willReturn($currencyMock); + $this->assertEquals($currencySymbol, $this->currency->getCurrencySymbol()); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/PriceCurrencyTest.php b/app/code/Magento/Directory/Test/Unit/Model/PriceCurrencyTest.php index 205a63e7b0c33f3ffaa312cf9256ee2607f4aab8..b934435151a040f0f7156c532aecdb85f313e6e8 100644 --- a/app/code/Magento/Directory/Test/Unit/Model/PriceCurrencyTest.php +++ b/app/code/Magento/Directory/Test/Unit/Model/PriceCurrencyTest.php @@ -168,6 +168,18 @@ class PriceCurrencyTest extends \PHPUnit_Framework_TestCase )); } + public function testGetCurrencySymbol() + { + $storeId = 2; + $currencySymbol = '$'; + + $currencyMock = $this->getCurrentCurrencyMock(); + $currencyMock->expects($this->once()) + ->method('getCurrencySymbol') + ->willReturn($currencySymbol); + $this->assertEquals($currencySymbol, $this->priceCurrency->getCurrencySymbol($storeId, $currencyMock)); + } + protected function getCurrentCurrencyMock() { $currency = $this->getMockBuilder('Magento\Directory\Model\Currency') diff --git a/app/code/Magento/Directory/composer.json b/app/code/Magento/Directory/composer.json index bc25eea4a4f6717ae53a92714ecf462bfa6f0e6d..610a919710b954d481569fce81e506a5b41f00ab 100644 --- a/app/code/Magento/Directory/composer.json +++ b/app/code/Magento/Directory/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Downloadable/Api/Data/LinkContentInterface.php b/app/code/Magento/Downloadable/Api/Data/LinkContentInterface.php deleted file mode 100644 index 1972068f435512611b3d564f875ec666f6d20b56..0000000000000000000000000000000000000000 --- a/app/code/Magento/Downloadable/Api/Data/LinkContentInterface.php +++ /dev/null @@ -1,194 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Downloadable\Api\Data; - -/** - * @codeCoverageIgnore - */ -interface LinkContentInterface extends \Magento\Framework\Api\ExtensibleDataInterface -{ - /** - * Retrieve sample title - * - * @return string - */ - public function getTitle(); - - /** - * Set sample title - * - * @param string $title - * @return $this - */ - public function setTitle($title); - - /** - * Retrieve sample sort order - * - * @return int - */ - public function getSortOrder(); - - /** - * Set sample sort order - * - * @param int $sortOrder - * @return $this - */ - public function setSortOrder($sortOrder); - - /** - * Retrieve link price - * - * @return string - */ - public function getPrice(); - - /** - * Set link price - * - * @param string $price - * @return $this - */ - public function setPrice($price); - - /** - * Retrieve number of allowed downloads of the link - * - * @return int - */ - public function getNumberOfDownloads(); - - /** - * Set number of allowed downloads of the link - * - * @param int $numberOfDownloads - * @return $this - */ - public function setNumberOfDownloads($numberOfDownloads); - - /** - * Check if link is shareable - * - * @return bool - */ - public function isShareable(); - - /** - * Set whether link is shareable - * - * @param bool $shareable - * @return $this - */ - public function setShareable($shareable); - - /** - * Retrieve link file content - * - * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null - */ - public function getLinkFile(); - - /** - * Set link file content - * - * @param \Magento\Downloadable\Api\Data\File\ContentInterface $linkFile - * @return $this - */ - public function setLinkFile(\Magento\Downloadable\Api\Data\File\ContentInterface $linkFile = null); - - /** - * Retrieve link URL - * - * @return string|null - */ - public function getLinkUrl(); - - /** - * Set link URL - * - * @param string $linkUrl - * @return $this - */ - public function setLinkUrl($linkUrl); - - /** - * Retrieve link type ('url' or 'file') - * - * @return string|null - */ - public function getLinkType(); - - /** - * Set link type ('url' or 'file') - * - * @param string $linkType - * @return $this - */ - public function setLinkType($linkType); - - /** - * Retrieve sample file content - * - * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null - */ - public function getSampleFile(); - - /** - * Retrieve sample file content - * - * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile - * @return $this - */ - public function setSampleFile(\Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile = null); - - /** - * Retrieve sample URL - * - * @return string|null - */ - public function getSampleUrl(); - - /** - * Set sample URL - * - * @param string $sampleUrl - * @return $this - */ - public function setSampleUrl($sampleUrl); - - /** - * Retrieve sample type ('url' or 'file') - * - * @return string|null - */ - public function getSampleType(); - - /** - * Set sample type ('url' or 'file') - * - * @param string $sampleType - * @return $this - */ - public function setSampleType($sampleType); - - /** - * Retrieve existing extension attributes object or create a new one. - * - * @return \Magento\Downloadable\Api\Data\LinkContentExtensionInterface|null - */ - public function getExtensionAttributes(); - - /** - * Set an extension attributes object. - * - * @param \Magento\Downloadable\Api\Data\LinkContentExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Downloadable\Api\Data\LinkContentExtensionInterface $extensionAttributes - ); -} diff --git a/app/code/Magento/Downloadable/Api/Data/LinkInterface.php b/app/code/Magento/Downloadable/Api/Data/LinkInterface.php index 0152a1a256540db9b0cab423e2804bd906475245..6fe62e070349e96c265a7d6d5e32da64de0eb976 100644 --- a/app/code/Magento/Downloadable/Api/Data/LinkInterface.php +++ b/app/code/Magento/Downloadable/Api/Data/LinkInterface.php @@ -119,9 +119,24 @@ interface LinkInterface extends \Magento\Framework\Api\ExtensibleDataInterface public function setLinkFile($linkFile); /** - * Return URL or NULL when type is 'file' + * Return file content * - * @return string|null file URL + * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null + */ + public function getLinkFileContent(); + + /** + * Set file content + * + * @param \Magento\Downloadable\Api\Data\File\ContentInterface $linkFileContent + * @return $this + */ + public function setLinkFileContent(\Magento\Downloadable\Api\Data\File\ContentInterface $linkFileContent = null); + + /** + * Return link url or null when type is 'file' + * + * @return string|null */ public function getLinkUrl(); @@ -159,6 +174,23 @@ interface LinkInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ public function setSampleFile($sampleFile); + /** + * Return sample file content when type is 'file' + * + * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null relative file path + */ + public function getSampleFileContent(); + + /** + * Set sample file content + * + * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFileContent + * @return $this + */ + public function setSampleFileContent( + \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFileContent = null + ); + /** * Return URL or NULL when type is 'file' * diff --git a/app/code/Magento/Downloadable/Api/Data/SampleContentInterface.php b/app/code/Magento/Downloadable/Api/Data/SampleContentInterface.php deleted file mode 100644 index b4b0580bda1879b6aa75ab70371f6c522b7d1100..0000000000000000000000000000000000000000 --- a/app/code/Magento/Downloadable/Api/Data/SampleContentInterface.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Downloadable\Api\Data; - -/** - * @codeCoverageIgnore - */ -interface SampleContentInterface extends \Magento\Framework\Api\ExtensibleDataInterface -{ - /** - * Retrieve sample title - * - * @return string - */ - public function getTitle(); - - /** - * Set sample title - * - * @param string $title - * @return $this - */ - public function setTitle($title); - - /** - * Retrieve sample type ('url' or 'file') - * - * @return string|null - */ - public function getSampleType(); - - /** - * Set sample type ('url' or 'file') - * - * @param string $sampleType - * @return $this - */ - public function setSampleType($sampleType); - - /** - * Retrieve sample file content - * - * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null - */ - public function getSampleFile(); - - /** - * Set sample file content - * - * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile - * @return $this - */ - public function setSampleFile(\Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile = null); - - /** - * Retrieve sample sort order - * - * @return int - */ - public function getSortOrder(); - - /** - * Set sample sort order - * - * @param int $sortOrder - * @return $this - */ - public function setSortOrder($sortOrder); - - /** - * Retrieve sample URL - * - * @return string|null - */ - public function getSampleUrl(); - - /** - * Set sample URL - * - * @param string $sampleUrl - * @return $this - */ - public function setSampleUrl($sampleUrl); - - /** - * Retrieve existing extension attributes object or create a new one. - * - * @return \Magento\Downloadable\Api\Data\SampleContentExtensionInterface|null - */ - public function getExtensionAttributes(); - - /** - * Set an extension attributes object. - * - * @param \Magento\Downloadable\Api\Data\SampleContentExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Downloadable\Api\Data\SampleContentExtensionInterface $extensionAttributes - ); -} diff --git a/app/code/Magento/Downloadable/Api/Data/SampleInterface.php b/app/code/Magento/Downloadable/Api/Data/SampleInterface.php index 3d6dfc937f3871a4a489e43c1f1912c5a7498082..8e30bf6f0e1ea0f3fc8bcf78b4261696e6119106 100644 --- a/app/code/Magento/Downloadable/Api/Data/SampleInterface.php +++ b/app/code/Magento/Downloadable/Api/Data/SampleInterface.php @@ -5,6 +5,8 @@ */ namespace Magento\Downloadable\Api\Data; +use \Magento\Downloadable\Api\Data\File\ContentInterface; + /** * @codeCoverageIgnore */ @@ -82,6 +84,21 @@ interface SampleInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ public function setSampleFile($sampleFile); + /** + * Retrieve sample file content + * + * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null + */ + public function getSampleFileContent(); + + /** + * Set sample file content + * + * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFileContent + * @return $this + */ + public function setSampleFileContent(ContentInterface $sampleFileContent = null); + /** * Return URL or NULL when type is 'file' * diff --git a/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php b/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php index a8bd6f83d9be190834e0e92d34c039010a4d870c..3a0d8053e4f8d599af652e83d830ad6c7ead7b65 100644 --- a/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php +++ b/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php @@ -5,7 +5,7 @@ */ namespace Magento\Downloadable\Api; -use Magento\Downloadable\Api\Data\LinkContentInterface; +use Magento\Downloadable\Api\Data\LinkInterface; interface LinkRepositoryInterface { @@ -17,6 +17,14 @@ interface LinkRepositoryInterface */ public function getSamples($sku); + /** + * List of samples for downloadable product + * + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return \Magento\Downloadable\Api\Data\SampleInterface[] + */ + public function getSamplesByProduct(\Magento\Catalog\Api\Data\ProductInterface $product); + /** * List of links with associated samples * @@ -25,22 +33,29 @@ interface LinkRepositoryInterface */ public function getLinks($sku); + /** + * List of links with associated samples + * + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return \Magento\Downloadable\Api\Data\LinkInterface[] + */ + public function getLinksByProduct(\Magento\Catalog\Api\Data\ProductInterface $product); + /** * Update downloadable link of the given product (link type and its resources cannot be changed) * * @param string $sku - * @param \Magento\Downloadable\Api\Data\LinkContentInterface $linkContent - * @param int $linkId + * @param \Magento\Downloadable\Api\Data\LinkInterface $link * @param bool $isGlobalScopeContent * @return int */ - public function save($sku, LinkContentInterface $linkContent, $linkId = null, $isGlobalScopeContent = false); + public function save($sku, LinkInterface $link, $isGlobalScopeContent = false); /** * Delete downloadable link * - * @param int $linkId + * @param int $id * @return bool */ - public function delete($linkId); + public function delete($id); } diff --git a/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php b/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php index cd72680b21bae5b75bd3b245d5a867ebd8e7f168..9a52cea8819f4e413e8c5a1964e5732e5936ed6f 100644 --- a/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php +++ b/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php @@ -5,31 +5,29 @@ */ namespace Magento\Downloadable\Api; -use Magento\Downloadable\Api\Data\SampleContentInterface; +use Magento\Downloadable\Api\Data\SampleInterface; interface SampleRepositoryInterface { /** - * Update downloadable sample of the given product (sample type and its resource cannot be changed) + * Update downloadable sample of the given product * - * @param string $productSku - * @param \Magento\Downloadable\Api\Data\SampleContentInterface $sampleContent - * @param int $sampleId + * @param string $sku + * @param \Magento\Downloadable\Api\Data\SampleInterface $sample * @param bool $isGlobalScopeContent * @return int */ public function save( - $productSku, - SampleContentInterface $sampleContent, - $sampleId = null, + $sku, + SampleInterface $sample, $isGlobalScopeContent = false ); /** * Delete downloadable sample * - * @param int $sampleId + * @param int $id * @return bool */ - public function delete($sampleId); + public function delete($id); } diff --git a/app/code/Magento/Downloadable/Model/Link.php b/app/code/Magento/Downloadable/Model/Link.php index 84de54915ab0edec47b492ac19a2fde4f5d131b4..66703a9dccb811ce294d5c4b39b053db7ec07cc2 100644 --- a/app/code/Magento/Downloadable/Model/Link.php +++ b/app/code/Magento/Downloadable/Model/Link.php @@ -43,9 +43,11 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements C const KEY_NUMBER_OF_DOWNLOADS = 'number_of_downloads'; const KEY_LINK_TYPE = 'link_type'; const KEY_LINK_FILE = 'link_file'; + const KEY_LINK_FILE_CONTENT = 'link_file_content'; const KEY_LINK_URL = 'link_url'; const KEY_SAMPLE_TYPE = 'sample_type'; const KEY_SAMPLE_FILE = 'sample_file'; + const KEY_SAMPLE_FILE_CONTENT = 'sample_file_content'; const KEY_SAMPLE_URL = 'sample_url'; /**#@-*/ @@ -213,6 +215,16 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements C return $this->getData(self::KEY_LINK_FILE); } + /** + * Return file content + * + * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null + */ + public function getLinkFileContent() + { + return $this->getData(self::KEY_LINK_FILE_CONTENT); + } + /** * {@inheritdoc} * @codeCoverageIgnore @@ -240,6 +252,16 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements C return $this->getData(self::KEY_SAMPLE_FILE); } + /** + * Return sample file content when type is 'file' + * + * @return \Magento\Downloadable\Api\Data\File\ContentInterface|null relative file path + */ + public function getSampleFileContent() + { + return $this->getData(self::KEY_SAMPLE_FILE_CONTENT); + } + /** * {@inheritdoc} * @codeCoverageIgnore @@ -320,6 +342,17 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements C return $this->setData(self::KEY_LINK_FILE, $linkFile); } + /** + * Set file content + * + * @param \Magento\Downloadable\Api\Data\File\ContentInterface $linkFileContent + * @return $this + */ + public function setLinkFileContent(\Magento\Downloadable\Api\Data\File\ContentInterface $linkFileContent = null) + { + return $this->setData(self::KEY_LINK_FILE_CONTENT, $linkFileContent); + } + /** * Set URL * @@ -351,6 +384,19 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements C return $this->setData(self::KEY_SAMPLE_FILE, $sampleFile); } + /** + * Set sample file content + * + * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFileContent + * @return $this + */ + public function setSampleFileContent( + \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFileContent = null + ) { + return $this->setData(self::KEY_SAMPLE_FILE_CONTENT, $sampleFileContent); + } + + /** * Set URL * diff --git a/app/code/Magento/Downloadable/Model/Link/Content.php b/app/code/Magento/Downloadable/Model/Link/Content.php deleted file mode 100644 index a40f76faf1cff5c353a8406943c9b51b4f95e428..0000000000000000000000000000000000000000 --- a/app/code/Magento/Downloadable/Model/Link/Content.php +++ /dev/null @@ -1,268 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Downloadable\Model\Link; - -use Magento\Downloadable\Api\Data\LinkContentInterface; - -/** - * @codeCoverageIgnore - */ -class Content extends \Magento\Framework\Model\AbstractExtensibleModel implements LinkContentInterface -{ - const TITLE = 'title'; - const PRICE = 'price'; - const NUMBER_OF_DOWNLOADS = 'number_of_downloads'; - const SHAREABLE = 'shareable'; - const SORT_ORDER = 'sort_order'; - const LINK_FILE = 'link_file'; - const LINK_URL = 'link_url'; - const LINK_TYPE = 'link_type'; - const SAMPLE_FILE = 'sample_file'; - const SAMPLE_URL = 'sample_url'; - const SAMPLE_TYPE = 'sample_type'; - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getTitle() - { - return $this->getData(self::TITLE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSortOrder() - { - return $this->getData(self::SORT_ORDER); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getPrice() - { - return $this->getData(self::PRICE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getNumberOfDownloads() - { - return $this->getData(self::NUMBER_OF_DOWNLOADS); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function isShareable() - { - return $this->getData(self::SHAREABLE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getLinkFile() - { - return $this->getData(self::LINK_FILE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getLinkUrl() - { - return $this->getData(self::LINK_URL); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getLinkType() - { - return $this->getData(self::LINK_TYPE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSampleFile() - { - return $this->getData(self::SAMPLE_FILE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSampleUrl() - { - return $this->getData(self::SAMPLE_URL); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSampleType() - { - return $this->getData(self::SAMPLE_TYPE); - } - - /** - * Set sample title - * - * @param string $title - * @return $this - */ - public function setTitle($title) - { - return $this->setData(self::TITLE, $title); - } - - /** - * Set sample sort order - * - * @param int $sortOrder - * @return $this - */ - public function setSortOrder($sortOrder) - { - return $this->setData(self::SORT_ORDER, $sortOrder); - } - - /** - * Set link price - * - * @param string $price - * @return $this - */ - public function setPrice($price) - { - return $this->setData(self::PRICE, $price); - } - - /** - * Set number of allowed downloads of the link - * - * @param int $numberOfDownloads - * @return $this - */ - public function setNumberOfDownloads($numberOfDownloads) - { - return $this->setData(self::NUMBER_OF_DOWNLOADS, $numberOfDownloads); - } - - /** - * Set whether link is shareable - * - * @param bool $shareable - * @return $this - */ - public function setShareable($shareable) - { - return $this->setData(self::SHAREABLE, $shareable); - } - - /** - * Set link file content - * - * @param \Magento\Downloadable\Api\Data\File\ContentInterface $linkFile - * @return $this - */ - public function setLinkFile(\Magento\Downloadable\Api\Data\File\ContentInterface $linkFile = null) - { - return $this->setData(self::LINK_FILE, $linkFile); - } - - /** - * Set link URL - * - * @param string $linkUrl - * @return $this - */ - public function setLinkUrl($linkUrl) - { - return $this->setData(self::LINK_URL, $linkUrl); - } - - /** - * Set link type ('url' or 'file') - * - * @param string $linkType - * @return $this - */ - public function setLinkType($linkType) - { - return $this->setData(self::LINK_TYPE, $linkType); - } - - /** - * Retrieve sample file content - * - * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile - * @return $this - */ - public function setSampleFile(\Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile = null) - { - return $this->setData(self::SAMPLE_FILE, $sampleFile); - } - - /** - * Set sample URL - * - * @param string $sampleUrl - * @return $this - */ - public function setSampleUrl($sampleUrl) - { - return $this->setData(self::SAMPLE_URL, $sampleUrl); - } - - /** - * Set sample type ('url' or 'file') - * - * @param string $sampleType - * @return $this - */ - public function setSampleType($sampleType) - { - return $this->setData(self::SAMPLE_TYPE, $sampleType); - } - - /** - * {@inheritdoc} - * - * @return \Magento\Downloadable\Api\Data\LinkContentExtensionInterface|null - */ - public function getExtensionAttributes() - { - return $this->_getExtensionAttributes(); - } - - /** - * {@inheritdoc} - * - * @param \Magento\Downloadable\Api\Data\LinkContentExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Downloadable\Api\Data\LinkContentExtensionInterface $extensionAttributes - ) { - return $this->_setExtensionAttributes($extensionAttributes); - } -} diff --git a/app/code/Magento/Downloadable/Model/Link/ContentValidator.php b/app/code/Magento/Downloadable/Model/Link/ContentValidator.php index 708302b7871c21c7bd1921b7a522019cbcd25aef..f1bf1d2dcbe85f819a0af7091d8806bee9cdcc12 100644 --- a/app/code/Magento/Downloadable/Model/Link/ContentValidator.php +++ b/app/code/Magento/Downloadable/Model/Link/ContentValidator.php @@ -5,7 +5,7 @@ */ namespace Magento\Downloadable\Model\Link; -use Magento\Downloadable\Api\Data\LinkContentInterface; +use Magento\Downloadable\Api\Data\LinkInterface; use Magento\Downloadable\Model\File\ContentValidator as FileContentValidator; use Magento\Framework\Exception\InputException; use Magento\Framework\Url\Validator as UrlValidator; @@ -37,43 +37,50 @@ class ContentValidator /** * Check if link content is valid * - * @param LinkContentInterface $linkContent + * @param LinkInterface $link + * @param bool $validateLinkContent + * @param bool $validateSampleContent * @return bool * @throws InputException */ - public function isValid(LinkContentInterface $linkContent) + public function isValid(LinkInterface $link, $validateLinkContent = true, $validateSampleContent = true) { - if (!is_numeric($linkContent->getPrice()) || $linkContent->getPrice() < 0) { + if (!is_numeric($link->getPrice()) || $link->getPrice() < 0) { throw new InputException(__('Link price must have numeric positive value.')); } - if (!is_int($linkContent->getNumberOfDownloads()) || $linkContent->getNumberOfDownloads() < 0) { + if (!is_int($link->getNumberOfDownloads()) || $link->getNumberOfDownloads() < 0) { throw new InputException(__('Number of downloads must be a positive integer.')); } - if (!is_int($linkContent->getSortOrder()) || $linkContent->getSortOrder() < 0) { + if (!is_int($link->getSortOrder()) || $link->getSortOrder() < 0) { throw new InputException(__('Sort order must be a positive integer.')); } - $this->validateLinkResource($linkContent); - $this->validateSampleResource($linkContent); + if ($validateLinkContent) { + $this->validateLinkResource($link); + } + if ($validateSampleContent) { + $this->validateSampleResource($link); + } return true; } /** * Validate link resource (file or URL) * - * @param LinkContentInterface $linkContent + * @param LinkInterface $link * @throws InputException * @return void */ - protected function validateLinkResource(LinkContentInterface $linkContent) + protected function validateLinkResource(LinkInterface $link) { - if ($linkContent->getLinkType() == 'url' - && !$this->urlValidator->isValid($linkContent->getLinkUrl()) + if ($link->getLinkType() == 'url' + && !$this->urlValidator->isValid($link->getLinkUrl()) ) { throw new InputException(__('Link URL must have valid format.')); } - if ($linkContent->getLinkType() == 'file' - && (!$linkContent->getLinkFile() || !$this->fileContentValidator->isValid($linkContent->getLinkFile())) + if ($link->getLinkType() == 'file' + && (!$link->getLinkFileContent() + || !$this->fileContentValidator->isValid($link->getLinkFileContent())) ) { throw new InputException(__('Provided file content must be valid base64 encoded data.')); } @@ -82,19 +89,20 @@ class ContentValidator /** * Validate sample resource (file or URL) * - * @param LinkContentInterface $linkContent + * @param LinkInterface $link * @throws InputException * @return void */ - protected function validateSampleResource(LinkContentInterface $linkContent) + protected function validateSampleResource(LinkInterface $link) { - if ($linkContent->getSampleType() == 'url' - && !$this->urlValidator->isValid($linkContent->getSampleUrl()) + if ($link->getSampleType() == 'url' + && !$this->urlValidator->isValid($link->getSampleUrl()) ) { throw new InputException(__('Sample URL must have valid format.')); } - if ($linkContent->getSampleType() == 'file' - && (!$linkContent->getSampleFile() || !$this->fileContentValidator->isValid($linkContent->getSampleFile())) + if ($link->getSampleType() == 'file' + && (!$link->getSampleFileContent() + || !$this->fileContentValidator->isValid($link->getSampleFileContent())) ) { throw new InputException(__('Provided file content must be valid base64 encoded data.')); } diff --git a/app/code/Magento/Downloadable/Model/LinkRepository.php b/app/code/Magento/Downloadable/Model/LinkRepository.php index 426e8bf63f21ed644dae4394470c8bf71d6482b4..bca06682ba718dee04cdd59e0edbfc275cc18efb 100644 --- a/app/code/Magento/Downloadable/Model/LinkRepository.php +++ b/app/code/Magento/Downloadable/Model/LinkRepository.php @@ -5,7 +5,7 @@ */ namespace Magento\Downloadable\Model; -use Magento\Downloadable\Api\Data\LinkContentInterface; +use Magento\Downloadable\Api\Data\LinkInterface; use Magento\Downloadable\Api\Data\File\ContentUploaderInterface; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; @@ -92,9 +92,18 @@ class LinkRepository implements \Magento\Downloadable\Api\LinkRepositoryInterfac */ public function getLinks($sku) { - $linkList = []; /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productRepository->get($sku); + return $this->getLinksByProduct($product); + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return array + */ + public function getLinksByProduct(\Magento\Catalog\Api\Data\ProductInterface $product) + { + $linkList = []; $links = $this->downloadableType->getLinks($product); /** @var \Magento\Downloadable\Model\Link $link */ foreach ($links as $link) { @@ -152,9 +161,17 @@ class LinkRepository implements \Magento\Downloadable\Api\LinkRepositoryInterfac */ public function getSamples($sku) { - $sampleList = []; - /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productRepository->get($sku); + return $this->getSamplesByProduct($product); + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return array + */ + public function getSamplesByProduct(\Magento\Catalog\Api\Data\ProductInterface $product) + { + $sampleList = []; $samples = $this->downloadableType->getSamples($product); /** @var \Magento\Downloadable\Model\Sample $sample */ foreach ($samples as $sample) { @@ -181,113 +198,149 @@ class LinkRepository implements \Magento\Downloadable\Api\LinkRepositoryInterfac * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function save($sku, LinkContentInterface $linkContent, $linkId = null, $isGlobalScopeContent = false) + public function save($sku, LinkInterface $link, $isGlobalScopeContent = false) { $product = $this->productRepository->get($sku, true); - if ($linkId) { - - /** @var $link \Magento\Downloadable\Model\Link */ - $link = $this->linkFactory->create()->load($linkId); - if (!$link->getId()) { - throw new NoSuchEntityException(__('There is no downloadable link with provided ID.')); - } - if ($link->getProductId() != $product->getId()) { - throw new InputException(__('Provided downloadable link is not related to given product.')); - } - if (!$this->contentValidator->isValid($linkContent)) { - throw new InputException(__('Provided link information is invalid.')); - } - if ($isGlobalScopeContent) { - $product->setStoreId(0); - } - $title = $linkContent->getTitle(); - if (empty($title)) { - if ($isGlobalScopeContent) { - throw new InputException(__('Link title cannot be empty.')); - } - // use title from GLOBAL scope - $link->setTitle(null); - } else { - $link->setTitle($linkContent->getTitle()); - } - - $link->setProductId($product->getId()) - ->setStoreId($product->getStoreId()) - ->setWebsiteId($product->getStore()->getWebsiteId()) - ->setProductWebsiteIds($product->getWebsiteIds()) - ->setSortOrder($linkContent->getSortOrder()) - ->setPrice($linkContent->getPrice()) - ->setIsShareable($linkContent->isShareable()) - ->setNumberOfDownloads($linkContent->getNumberOfDownloads()) - ->save(); - return $link->getId(); + if ($link->getId() !== null) { + return $this->updateLink($product, $link, $isGlobalScopeContent); } else { - $product = $this->productRepository->get($sku, true); if ($product->getTypeId() !== \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { throw new InputException(__('Product type of the product must be \'downloadable\'.')); } - if (!$this->contentValidator->isValid($linkContent)) { + if (!$this->contentValidator->isValid($link)) { throw new InputException(__('Provided link information is invalid.')); } - if (!in_array($linkContent->getLinkType(), ['url', 'file'])) { + if (!in_array($link->getLinkType(), ['url', 'file'])) { throw new InputException(__('Invalid link type.')); } - $title = $linkContent->getTitle(); + $title = $link->getTitle(); if (empty($title)) { throw new InputException(__('Link title cannot be empty.')); } + return $this->saveLink($product, $link, $isGlobalScopeContent); + } + } - $linkData = [ - 'link_id' => 0, - 'is_delete' => 0, - 'type' => $linkContent->getLinkType(), - 'sort_order' => $linkContent->getSortOrder(), - 'title' => $linkContent->getTitle(), - 'price' => $linkContent->getPrice(), - 'number_of_downloads' => $linkContent->getNumberOfDownloads(), - 'is_shareable' => $linkContent->isShareable(), - ]; + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param LinkInterface $link + * @param bool $isGlobalScopeContent + * @return int + */ + protected function saveLink( + \Magento\Catalog\Api\Data\ProductInterface $product, + LinkInterface $link, + $isGlobalScopeContent + ) { + $linkData = [ + 'link_id' => $link->getid() === null ? 0 : $link->getid(), + 'is_delete' => 0, + 'type' => $link->getLinkType(), + 'sort_order' => $link->getSortOrder(), + 'title' => $link->getTitle(), + 'price' => $link->getPrice(), + 'number_of_downloads' => $link->getNumberOfDownloads(), + 'is_shareable' => $link->getIsShareable(), + ]; - if ($linkContent->getLinkType() == 'file') { - $linkData['file'] = $this->jsonEncoder->encode( + if ($link->getLinkType() == 'file' && $link->getLinkFile() === null) { + $linkData['file'] = $this->jsonEncoder->encode( + [ + $this->fileContentUploader->upload($link->getLinkFileContent(), 'link_file'), + ] + ); + } elseif ($link->getLinkType() === 'url') { + $linkData['link_url'] = $link->getLinkUrl(); + } else { + //existing link file + $linkData['file'] = $this->jsonEncoder->encode( + [ [ - $this->fileContentUploader->upload($linkContent->getLinkFile(), 'link_file'), + 'file' => $link->getLinkFile(), + 'status' => 'old', ] - ); - } else { - $linkData['link_url'] = $linkContent->getLinkUrl(); - } + ] + ); + } - if ($linkContent->getSampleType() == 'file') { - $linkData['sample']['type'] = 'file'; - $linkData['sample']['file'] = $this->jsonEncoder->encode( - [ - $this->fileContentUploader->upload($linkContent->getSampleFile(), 'link_sample_file'), - ] - ); - } elseif ($linkContent->getSampleType() == 'url') { - $linkData['sample']['type'] = 'url'; - $linkData['sample']['url'] = $linkContent->getSampleUrl(); - } + if ($link->getSampleType() == 'file' && $link->getSampleFile() === null) { + $linkData['sample']['type'] = 'file'; + $linkData['sample']['file'] = $this->jsonEncoder->encode( + [ + $this->fileContentUploader->upload($link->getSampleFileContent(), 'link_sample_file'), + ] + ); + } elseif ($link->getSampleType() == 'url') { + $linkData['sample']['type'] = 'url'; + $linkData['sample']['url'] = $link->getSampleUrl(); + } - $downloadableData = ['link' => [$linkData]]; - $product->setDownloadableData($downloadableData); + $downloadableData = ['link' => [$linkData]]; + $product->setDownloadableData($downloadableData); + if ($isGlobalScopeContent) { + $product->setStoreId(0); + } + $this->downloadableType->save($product); + return $product->getLastAddedLinkId(); + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param LinkInterface $link + * @param bool $isGlobalScopeContent + * @return mixed + * @throws InputException + * @throws NoSuchEntityException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function updateLink( + \Magento\Catalog\Api\Data\ProductInterface $product, + LinkInterface $link, + $isGlobalScopeContent + ) { + /** @var $existingLink \Magento\Downloadable\Model\Link */ + $existingLink = $this->linkFactory->create()->load($link->getId()); + if (!$existingLink->getId()) { + throw new NoSuchEntityException(__('There is no downloadable link with provided ID.')); + } + if ($existingLink->getProductId() != $product->getId()) { + throw new InputException(__('Provided downloadable link is not related to given product.')); + } + $validateLinkContent = $link->getLinkFileContent() === null ? false : true; + $validateSampleContent = $link->getSampleFileContent() === null ? false : true; + if (!$this->contentValidator->isValid($link, $validateLinkContent, $validateSampleContent)) { + throw new InputException(__('Provided link information is invalid.')); + } + if ($isGlobalScopeContent) { + $product->setStoreId(0); + } + $title = $link->getTitle(); + if (empty($title)) { if ($isGlobalScopeContent) { - $product->setStoreId(0); + throw new InputException(__('Link title cannot be empty.')); } - $product->save(); - return $product->getLastAddedLinkId(); } + + if ($link->getLinkType() == 'file' && $link->getLinkFileContent() === null) { + $link->setLinkFile($existingLink->getLinkFile()); + } + if ($link->getSampleType() == 'file' && $link->getSampleFileContent() === null) { + $link->setSampleFile($existingLink->getSampleFile()); + } + + $this->saveLink($product, $link, $isGlobalScopeContent); + return $existingLink->getId(); } /** * {@inheritdoc} */ - public function delete($linkId) + public function delete($id) { /** @var $link \Magento\Downloadable\Model\Link */ - $link = $this->linkFactory->create()->load($linkId); + $link = $this->linkFactory->create()->load($id); if (!$link->getId()) { throw new NoSuchEntityException(__('There is no downloadable link with provided ID.')); } diff --git a/app/code/Magento/Downloadable/Model/Observer.php b/app/code/Magento/Downloadable/Model/Observer.php index 0fd516bfa9fafc120ee467f52725eb0e974de334..68dc8f018d7f00aef5a9556f6622d518bb924142 100644 --- a/app/code/Magento/Downloadable/Model/Observer.php +++ b/app/code/Magento/Downloadable/Model/Observer.php @@ -114,10 +114,10 @@ class Observer //order not saved in the database return $this; } - $product = $orderItem->getProduct(); - if ($product && $product->getTypeId() != \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { + if ($orderItem->getProductType() != \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { return $this; } + $product = $orderItem->getProduct(); $purchasedLink = $this->_createPurchasedModel()->load($orderItem->getId(), 'order_item_id'); if ($purchasedLink->getId()) { return $this; diff --git a/app/code/Magento/Downloadable/Model/Plugin/AfterProductLoad.php b/app/code/Magento/Downloadable/Model/Plugin/AfterProductLoad.php new file mode 100644 index 0000000000000000000000000000000000000000..83466a0fa080f34d7aa3d38fbcfd0fd8905d1101 --- /dev/null +++ b/app/code/Magento/Downloadable/Model/Plugin/AfterProductLoad.php @@ -0,0 +1,62 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Downloadable\Model\Plugin; + +class AfterProductLoad +{ + /** + * @var \Magento\Downloadable\Api\LinkRepositoryInterface + */ + protected $linkRepository; + + /** + * @var \Magento\Catalog\Api\Data\ProductExtensionFactory + */ + protected $productExtensionFactory; + + /** + * @param \Magento\Downloadable\Api\LinkRepositoryInterface $linkRepository + * @param \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory + */ + public function __construct( + \Magento\Downloadable\Api\LinkRepositoryInterface $linkRepository, + \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory + ) { + $this->linkRepository = $linkRepository; + $this->productExtensionFactory = $productExtensionFactory; + } + + /** + * @param \Magento\Catalog\Model\Product $product + * @return \Magento\Catalog\Model\Product + */ + public function afterLoad( + \Magento\Catalog\Model\Product $product + ) { + if ($product->getTypeId() != \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { + return $product; + } + + $productExtension = $product->getExtensionAttributes(); + if ($productExtension === null) { + $productExtension = $this->productExtensionFactory->create(); + } + $links = $this->linkRepository->getLinksByProduct($product); + if ($links !== null) { + $productExtension->setDownloadableProductLinks($links); + } + $samples = $this->linkRepository->getSamplesByProduct($product); + if ($samples !== null) { + $productExtension->setDownloadableProductSamples($samples); + } + + $product->setExtensionAttributes($productExtension); + + return $product; + } +} diff --git a/app/code/Magento/Downloadable/Model/Plugin/AroundProductRepositorySave.php b/app/code/Magento/Downloadable/Model/Plugin/AroundProductRepositorySave.php new file mode 100644 index 0000000000000000000000000000000000000000..13dd932c3a7683109c4fcef022556abb0dbfa519 --- /dev/null +++ b/app/code/Magento/Downloadable/Model/Plugin/AroundProductRepositorySave.php @@ -0,0 +1,145 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Downloadable\Model\Plugin; + +class AroundProductRepositorySave +{ + /** + * @var \Magento\Downloadable\Api\LinkRepositoryInterface + */ + protected $linkRepository; + + /** + * @var \Magento\Downloadable\Api\SampleRepositoryInterface + */ + protected $sampleRepository; + + /** + * @param \Magento\Downloadable\Api\LinkRepositoryInterface $linkRepository + * @param \Magento\Downloadable\Api\SampleRepositoryInterface $sampleRepository + */ + public function __construct( + \Magento\Downloadable\Api\LinkRepositoryInterface $linkRepository, + \Magento\Downloadable\Api\SampleRepositoryInterface $sampleRepository + ) { + $this->linkRepository = $linkRepository; + $this->sampleRepository = $sampleRepository; + } + + /** + * @param \Magento\Catalog\Api\ProductRepositoryInterface $subject + * @param callable $proceed + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param bool $saveOptions + * @return \Magento\Catalog\Api\Data\ProductInterface + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function aroundSave( + \Magento\Catalog\Api\ProductRepositoryInterface $subject, + \Closure $proceed, + \Magento\Catalog\Api\Data\ProductInterface $product, + $saveOptions = false + ) { + /** @var \Magento\Catalog\Api\Data\ProductInterface $result */ + $result = $proceed($product, $saveOptions); + + if ($product->getTypeId() != \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { + return $result; + } + + /* @var \Magento\Catalog\Api\Data\ProductExtensionInterface $options */ + $extendedAttributes = $product->getExtensionAttributes(); + if ($extendedAttributes === null) { + return $result; + } + $links = $extendedAttributes->getDownloadableProductLinks(); + $samples = $extendedAttributes->getDownloadableProductSamples(); + + if ($links === null && $samples === null) { + return $result; + } + + if ($links !== null) { + $this->saveLinks($result, $links); + } + if ($samples !== null) { + $this->saveSamples($result, $samples); + } + + return $subject->get($result->getSku(), false, $result->getStoreId(), true); + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param \Magento\Downloadable\Api\Data\LinkInterface[] $links + * @return $this + */ + protected function saveLinks(\Magento\Catalog\Api\Data\ProductInterface $product, array $links) + { + $existingLinkIds = []; + //get existing links from extension attribute + $extensionAttributes = $product->getExtensionAttributes(); + if ($extensionAttributes !== null) { + $existingLinks = $extensionAttributes->getDownloadableProductLinks(); + if ($existingLinks !== null) { + foreach ($existingLinks as $existingLink) { + $existingLinkIds[] = $existingLink->getId(); + } + } + } + + $updatedLinkIds = []; + foreach ($links as $link) { + $linkId = $link->getId(); + if ($linkId) { + $updatedLinkIds[] = $linkId; + } + $this->linkRepository->save($product->getSku(), $link); + } + $linkIdsToDelete = array_diff($existingLinkIds, $updatedLinkIds); + + foreach ($linkIdsToDelete as $linkId) { + $this->linkRepository->delete($linkId); + } + return $this; + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param \Magento\Downloadable\Api\Data\SampleInterface[] $samples + * @return $this + */ + protected function saveSamples(\Magento\Catalog\Api\Data\ProductInterface $product, array $samples) + { + $existingSampleIds = []; + $extensionAttributes = $product->getExtensionAttributes(); + if ($extensionAttributes !== null) { + $existingSamples = $extensionAttributes->getDownloadableProductSamples(); + if ($existingSamples !== null) { + foreach ($existingSamples as $existingSample) { + $existingSampleIds[] = $existingSample->getId(); + } + } + } + + $updatedSampleIds = []; + foreach ($samples as $sample) { + $sampleId = $sample->getId(); + if ($sampleId) { + $updatedSampleIds[] = $sampleId; + } + $this->sampleRepository->save($product->getSku(), $sample); + } + $sampleIdsToDelete = array_diff($existingSampleIds, $updatedSampleIds); + + foreach ($sampleIdsToDelete as $sampleId) { + $this->sampleRepository->delete($sampleId); + } + return $this; + } +} diff --git a/app/code/Magento/Downloadable/Model/Sample.php b/app/code/Magento/Downloadable/Model/Sample.php index 07dd821050aad1d60ae18abc38211afdd1fb4a55..4909fe6a39e649e071b47859b77a136eb31a1241 100644 --- a/app/code/Magento/Downloadable/Model/Sample.php +++ b/app/code/Magento/Downloadable/Model/Sample.php @@ -27,6 +27,7 @@ class Sample extends \Magento\Framework\Model\AbstractExtensibleModel implements const KEY_SORT_ORDER = 'sort_order'; const KEY_SAMPLE_TYPE = 'sample_type'; const KEY_SAMPLE_FILE = 'sample_file'; + const KEY_SAMPLE_FILE_CONTENT = 'sample_file_content'; const KEY_SAMPLE_URL = 'sample_url'; /**#@-*/ @@ -163,6 +164,15 @@ class Sample extends \Magento\Framework\Model\AbstractExtensibleModel implements return $this->getData(self::KEY_SAMPLE_FILE); } + /** + * {@inheritdoc} + * @codeCoverageIgnore + */ + public function getSampleFileContent() + { + return $this->getData(self::KEY_SAMPLE_FILE_CONTENT); + } + /** * {@inheritdoc} * @codeCoverageIgnore @@ -214,6 +224,17 @@ class Sample extends \Magento\Framework\Model\AbstractExtensibleModel implements return $this->setData(self::KEY_SAMPLE_FILE, $sampleFile); } + /** + * Set sample file content + * + * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFileContent + * @return $this + */ + public function setSampleFileContent(\Magento\Downloadable\Api\Data\File\ContentInterface $sampleFileContent = null) + { + return $this->setData(self::KEY_SAMPLE_FILE_CONTENT, $sampleFileContent); + } + /** * Set sample URL * diff --git a/app/code/Magento/Downloadable/Model/Sample/Content.php b/app/code/Magento/Downloadable/Model/Sample/Content.php deleted file mode 100644 index 0fcf613353966548cfbf6ec83e2ca47837ff9f54..0000000000000000000000000000000000000000 --- a/app/code/Magento/Downloadable/Model/Sample/Content.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Downloadable\Model\Sample; - -use Magento\Downloadable\Api\Data\SampleContentInterface; - -/** - * @codeCoverageIgnore - */ -class Content extends \Magento\Framework\Model\AbstractExtensibleModel implements SampleContentInterface -{ - const TITLE = 'title'; - const SORT_ORDER = 'sort_order'; - const SAMPLE_FILE = 'sample_file'; - const SAMPLE_URL = 'sample_url'; - const SAMPLE_TYPE = 'sample_type'; - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getTitle() - { - return $this->getData(self::TITLE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSampleType() - { - return $this->getData(self::SAMPLE_TYPE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSampleFile() - { - return $this->getData(self::SAMPLE_FILE); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSortOrder() - { - return $this->getData(self::SORT_ORDER); - } - - /** - * {@inheritdoc} - * @codeCoverageIgnore - */ - public function getSampleUrl() - { - return $this->getData(self::SAMPLE_URL); - } - - /** - * Set sample title - * - * @param string $title - * @return $this - */ - public function setTitle($title) - { - return $this->setData(self::TITLE, $title); - } - - /** - * Set sample type ('url' or 'file') - * - * @param string $sampleType - * @return $this - */ - public function setSampleType($sampleType) - { - return $this->setData(self::SAMPLE_TYPE, $sampleType); - } - - /** - * Set sample file content - * - * @param \Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile - * @return $this - */ - public function setSampleFile(\Magento\Downloadable\Api\Data\File\ContentInterface $sampleFile = null) - { - return $this->setData(self::SAMPLE_FILE, $sampleFile); - } - - /** - * Set sample sort order - * - * @param int $sortOrder - * @return $this - */ - public function setSortOrder($sortOrder) - { - return $this->setData(self::SORT_ORDER, $sortOrder); - } - - /** - * Set sample URL - * - * @param string $sampleUrl - * @return $this - */ - public function setSampleUrl($sampleUrl) - { - return $this->setData(self::SAMPLE_URL, $sampleUrl); - } - - /** - * {@inheritdoc} - * - * @return \Magento\Downloadable\Api\Data\SampleContentExtensionInterface|null - */ - public function getExtensionAttributes() - { - return $this->_getExtensionAttributes(); - } - - /** - * {@inheritdoc} - * - * @param \Magento\Downloadable\Api\Data\SampleContentExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Downloadable\Api\Data\SampleContentExtensionInterface $extensionAttributes - ) { - return $this->_setExtensionAttributes($extensionAttributes); - } -} diff --git a/app/code/Magento/Downloadable/Model/Sample/ContentValidator.php b/app/code/Magento/Downloadable/Model/Sample/ContentValidator.php index 294bd783d463560a5846eada1cc400f5e6a97ce7..83f44d1a5c1b07c20229193db238f53d93cfad6f 100644 --- a/app/code/Magento/Downloadable/Model/Sample/ContentValidator.php +++ b/app/code/Magento/Downloadable/Model/Sample/ContentValidator.php @@ -5,7 +5,7 @@ */ namespace Magento\Downloadable\Model\Sample; -use Magento\Downloadable\Api\Data\SampleContentInterface; +use Magento\Downloadable\Api\Data\SampleInterface; use Magento\Downloadable\Model\File\ContentValidator as FileContentValidator; use Magento\Framework\Exception\InputException; use Magento\Framework\Url\Validator as UrlValidator; @@ -37,38 +37,41 @@ class ContentValidator /** * Check if sample content is valid * - * @param SampleContentInterface $sampleContent + * @param SampleInterface $sample + * @param bool $validateSampleContent * @return bool * @throws InputException */ - public function isValid(SampleContentInterface $sampleContent) + public function isValid(SampleInterface $sample, $validateSampleContent = true) { - if (!is_int($sampleContent->getSortOrder()) || $sampleContent->getSortOrder() < 0) { + if (!is_int($sample->getSortOrder()) || $sample->getSortOrder() < 0) { throw new InputException(__('Sort order must be a positive integer.')); } - $this->validateSampleResource($sampleContent); + if ($validateSampleContent) { + $this->validateSampleResource($sample); + } return true; } /** * Validate sample resource (file or URL) * - * @param SampleContentInterface $sampleContent + * @param SampleInterface $sample * @throws InputException * @return void */ - protected function validateSampleResource(SampleContentInterface $sampleContent) + protected function validateSampleResource(SampleInterface $sample) { - $sampleFile = $sampleContent->getSampleFile(); - if ($sampleContent->getSampleType() == 'file' + $sampleFile = $sample->getSampleFileContent(); + if ($sample->getSampleType() == 'file' && (!$sampleFile || !$this->fileContentValidator->isValid($sampleFile)) ) { throw new InputException(__('Provided file content must be valid base64 encoded data.')); } - if ($sampleContent->getSampleType() == 'url' - && !$this->urlValidator->isValid($sampleContent->getSampleUrl()) + if ($sample->getSampleType() == 'url' + && !$this->urlValidator->isValid($sample->getSampleUrl()) ) { throw new InputException(__('Sample URL must have valid format.')); } diff --git a/app/code/Magento/Downloadable/Model/SampleRepository.php b/app/code/Magento/Downloadable/Model/SampleRepository.php index b97702bd9adaf8c143dbf0f62823c460121fe02c..f357e6a5d8541ce450fab6ee85cdb782dd8fcc4e 100644 --- a/app/code/Magento/Downloadable/Model/SampleRepository.php +++ b/app/code/Magento/Downloadable/Model/SampleRepository.php @@ -8,12 +8,17 @@ namespace Magento\Downloadable\Model; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Downloadable\Model\SampleFactory; use Magento\Downloadable\Api\Data\File\ContentUploaderInterface; -use Magento\Downloadable\Api\Data\SampleContentInterface; +use Magento\Downloadable\Api\Data\SampleInterface; use Magento\Downloadable\Model\Sample\ContentValidator; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Json\EncoderInterface; +/** + * Class SampleRepository + * @package Magento\Downloadable\Model + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInterface { /** @@ -21,6 +26,11 @@ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInte */ protected $productRepository; + /** + * @var \Magento\Downloadable\Model\Product\Type + */ + protected $downloadableType; + /** * @var ContentValidator */ @@ -38,6 +48,7 @@ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInte /** * @param ProductRepositoryInterface $productRepository + * @param \Magento\Downloadable\Model\Product\Type $downloadableType * @param ContentValidator $contentValidator * @param ContentUploaderInterface $fileContentUploader * @param EncoderInterface $jsonEncoder @@ -45,12 +56,14 @@ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInte */ public function __construct( ProductRepositoryInterface $productRepository, + \Magento\Downloadable\Model\Product\Type $downloadableType, ContentValidator $contentValidator, ContentUploaderInterface $fileContentUploader, EncoderInterface $jsonEncoder, SampleFactory $sampleFactory ) { $this->productRepository = $productRepository; + $this->downloadableType = $downloadableType; $this->contentValidator = $contentValidator; $this->fileContentUploader = $fileContentUploader; $this->jsonEncoder = $jsonEncoder; @@ -58,106 +71,153 @@ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInte } /** - * {@inheritdoc} + * Update downloadable sample of the given product + * + * @param string $sku + * @param \Magento\Downloadable\Api\Data\SampleInterface $sample + * @param bool $isGlobalScopeContent + * @return int * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function save( - $productSku, - SampleContentInterface $sampleContent, - $sampleId = null, + $sku, + SampleInterface $sample, $isGlobalScopeContent = false ) { - $product = $this->productRepository->get($productSku, true); + $product = $this->productRepository->get($sku, true); + $sampleId = $sample->getId(); if ($sampleId) { - - /** @var $sample \Magento\Downloadable\Model\Sample */ - $sample = $this->sampleFactory->create()->load($sampleId); - - if (!$sample->getId()) { - throw new NoSuchEntityException(__('There is no downloadable sample with provided ID.')); - } - - if ($sample->getProductId() != $product->getId()) { - throw new InputException(__('Provided downloadable sample is not related to given product.')); - } - if (!$this->contentValidator->isValid($sampleContent)) { - throw new InputException(__('Provided sample information is invalid.')); - } - if ($isGlobalScopeContent) { - $product->setStoreId(0); - } - - $title = $sampleContent->getTitle(); - if (empty($title)) { - if ($isGlobalScopeContent) { - throw new InputException(__('Sample title cannot be empty.')); - } - // use title from GLOBAL scope - $sample->setTitle(null); - } else { - $sample->setTitle($sampleContent->getTitle()); - } - - $sample->setProductId($product->getId()) - ->setStoreId($product->getStoreId()) - ->setSortOrder($sampleContent->getSortOrder()) - ->save(); - - return $sample->getId(); + return $this->updateSample($product, $sample, $isGlobalScopeContent); } else { - if ($product->getTypeId() !== \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { throw new InputException(__('Product type of the product must be \'downloadable\'.')); } - if (!$this->contentValidator->isValid($sampleContent)) { + if (!$this->contentValidator->isValid($sample)) { throw new InputException(__('Provided sample information is invalid.')); } - if (!in_array($sampleContent->getSampleType(), ['url', 'file'])) { + if (!in_array($sample->getSampleType(), ['url', 'file'])) { throw new InputException(__('Invalid sample type.')); } - $title = $sampleContent->getTitle(); + $title = $sample->getTitle(); if (empty($title)) { throw new InputException(__('Sample title cannot be empty.')); } - $sampleData = [ - 'sample_id' => 0, - 'is_delete' => 0, - 'type' => $sampleContent->getSampleType(), - 'sort_order' => $sampleContent->getSortOrder(), - 'title' => $sampleContent->getTitle(), - ]; + return $this->saveSample($product, $sample, $isGlobalScopeContent); + } + } - if ($sampleContent->getSampleType() == 'file') { - $sampleData['file'] = $this->jsonEncoder->encode( + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param SampleInterface $sample + * @param bool $isGlobalScopeContent + * @return int + */ + protected function saveSample( + \Magento\Catalog\Api\Data\ProductInterface $product, + SampleInterface $sample, + $isGlobalScopeContent + ) { + $sampleData = [ + 'sample_id' => $sample->getid() === null ? 0 : $sample->getid(), + 'is_delete' => 0, + 'type' => $sample->getSampleType(), + 'sort_order' => $sample->getSortOrder(), + 'title' => $sample->getTitle(), + ]; + + if ($sample->getSampleType() == 'file' && $sample->getSampleFile() === null) { + $sampleData['file'] = $this->jsonEncoder->encode( + [ + $this->fileContentUploader->upload($sample->getSampleFileContent(), 'sample'), + ] + ); + } elseif ($sample->getSampleType() === 'url') { + $sampleData['sample_url'] = $sample->getSampleUrl(); + } else { + //existing file + $sampleData['file'] = $this->jsonEncoder->encode( + [ [ - $this->fileContentUploader->upload($sampleContent->getSampleFile(), 'sample'), - ] - ); - } else { - $sampleData['sample_url'] = $sampleContent->getSampleUrl(); - } + 'file' => $sample->getSampleFile(), + 'status' => 'old', + ], + ] + ); + } + + $downloadableData = ['sample' => [$sampleData]]; + $product->setDownloadableData($downloadableData); + if ($isGlobalScopeContent) { + $product->setStoreId(0); + } + $this->downloadableType->save($product); + return $product->getLastAddedSampleId(); + } + + /** + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @param SampleInterface $sample + * @param bool $isGlobalScopeContent + * @return int + * @throws InputException + * @throws NoSuchEntityException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function updateSample( + \Magento\Catalog\Api\Data\ProductInterface $product, + SampleInterface $sample, + $isGlobalScopeContent + ) { + $sampleId = $sample->getId(); + /** @var $existingSample \Magento\Downloadable\Model\Sample */ + $existingSample = $this->sampleFactory->create()->load($sampleId); - $downloadableData = ['sample' => [$sampleData]]; - $product->setDownloadableData($downloadableData); + if (!$existingSample->getId()) { + throw new NoSuchEntityException(__('There is no downloadable sample with provided ID.')); + } + + if ($existingSample->getProductId() != $product->getId()) { + throw new InputException(__('Provided downloadable sample is not related to given product.')); + } + + $validateFileContent = $sample->getSampleFileContent() === null ? false : true; + if (!$this->contentValidator->isValid($sample, $validateFileContent)) { + throw new InputException(__('Provided sample information is invalid.')); + } + if ($isGlobalScopeContent) { + $product->setStoreId(0); + } + + $title = $sample->getTitle(); + if (empty($title)) { if ($isGlobalScopeContent) { - $product->setStoreId(0); + throw new InputException(__('Sample title cannot be empty.')); } - $product->save(); - return $product->getLastAddedSampleId(); + // use title from GLOBAL scope + $existingSample->setTitle(null); + } else { + $existingSample->setTitle($sample->getTitle()); + } + + if ($sample->getSampleType() === 'file' && $sample->getSampleFileContent() === null) { + $sample->setSampleFile($existingSample->getSampleFile()); } + $this->saveSample($product, $sample, $isGlobalScopeContent); + return $existingSample->getId(); } /** * {@inheritdoc} */ - public function delete($sampleId) + public function delete($id) { /** @var $sample \Magento\Downloadable\Model\Sample */ - $sample = $this->sampleFactory->create()->load($sampleId); + $sample = $this->sampleFactory->create()->load($id); if (!$sample->getId()) { throw new NoSuchEntityException(__('There is no downloadable sample with provided ID.')); } diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/Link/ContentValidatorTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/Link/ContentValidatorTest.php index 6e7a6555514b345535e784fc4b2e3abf8839c195..685d116b2b700cd10a286a22b604b435597ad3bb 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/Link/ContentValidatorTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/Link/ContentValidatorTest.php @@ -52,12 +52,14 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase ); $this->linkFileMock = $this->getMock('\Magento\Downloadable\Api\Data\File\ContentInterface'); $this->sampleFileMock = $this->getMock('\Magento\Downloadable\Api\Data\File\ContentInterface'); - $this->validator = new \Magento\Downloadable\Model\Link\ContentValidator($this->fileValidatorMock, $this->urlValidatorMock); + $this->validator = new ContentValidator($this->fileValidatorMock, $this->urlValidatorMock); } public function testIsValid() { - $linkContentData = [ + $linkFileContentMock = $this->getMock('Magento\Downloadable\Api\Data\File\ContentInterface'); + $sampleFileContentMock = $this->getMock('Magento\Downloadable\Api\Data\File\ContentInterface'); + $linkData = [ 'title' => 'Title', 'sort_order' => 1, 'price' => 10.1, @@ -65,11 +67,53 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase 'number_of_downloads' => 100, 'link_type' => 'file', 'sample_type' => 'file', + 'link_file_content' => $linkFileContentMock, + 'sample_file_content' => $sampleFileContentMock, ]; $this->fileValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); $this->urlValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); - $contentMock = $this->getLinkContentMock($linkContentData); - $this->assertTrue($this->validator->isValid($contentMock)); + $linkMock = $this->getLinkMock($linkData); + $this->assertTrue($this->validator->isValid($linkMock)); + } + + public function testIsValidSkipLinkContent() + { + $sampleFileContentMock = $this->getMock('Magento\Downloadable\Api\Data\File\ContentInterface'); + $linkData = [ + 'title' => 'Title', + 'sort_order' => 1, + 'price' => 10.1, + 'shareable' => true, + 'number_of_downloads' => 100, + 'link_type' => 'url', + 'link_url' => 'http://example.com', + 'sample_type' => 'file', + 'sample_file_content' => $sampleFileContentMock, + ]; + $this->fileValidatorMock->expects($this->once())->method('isValid')->will($this->returnValue(true)); + $this->urlValidatorMock->expects($this->never())->method('isValid')->will($this->returnValue(true)); + $linkMock = $this->getLinkMock($linkData); + $this->assertTrue($this->validator->isValid($linkMock, false)); + } + + public function testIsValidSkipSampleContent() + { + $sampleFileContentMock = $this->getMock('Magento\Downloadable\Api\Data\File\ContentInterface'); + $linkData = [ + 'title' => 'Title', + 'sort_order' => 1, + 'price' => 10.1, + 'shareable' => true, + 'number_of_downloads' => 100, + 'link_type' => 'url', + 'link_url' => 'http://example.com', + 'sample_type' => 'file', + 'sample_file_content' => $sampleFileContentMock, + ]; + $this->fileValidatorMock->expects($this->never())->method('isValid')->will($this->returnValue(true)); + $this->urlValidatorMock->expects($this->once())->method('isValid')->will($this->returnValue(true)); + $linkMock = $this->getLinkMock($linkData); + $this->assertTrue($this->validator->isValid($linkMock, true, false)); } /** @@ -91,7 +135,7 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase ]; $this->fileValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); $this->urlValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); - $contentMock = $this->getLinkContentMock($linkContentData); + $contentMock = $this->getLinkMock($linkContentData); $this->validator->isValid($contentMock); } @@ -126,7 +170,7 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase ]; $this->fileValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); $this->urlValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); - $contentMock = $this->getLinkContentMock($linkContentData); + $contentMock = $this->getLinkMock($linkContentData); $this->validator->isValid($contentMock); } @@ -160,7 +204,7 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase ]; $this->urlValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); $this->fileValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); - $contentMock = $this->getLinkContentMock($linkContentData); + $contentMock = $this->getLinkMock($linkContentData); $this->validator->isValid($contentMock); } @@ -177,51 +221,58 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase } /** - * @param array $linkContentData + * @param array $linkData * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function getLinkContentMock(array $linkContentData) + protected function getLinkMock(array $linkData) { - $contentMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkContentInterface'); - $contentMock->expects($this->any())->method('getTitle')->will($this->returnValue( - $linkContentData['title'] + $linkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $linkMock->expects($this->any())->method('getTitle')->will($this->returnValue( + $linkData['title'] )); - $contentMock->expects($this->any())->method('getPrice')->will($this->returnValue( - $linkContentData['price'] + $linkMock->expects($this->any())->method('getPrice')->will($this->returnValue( + $linkData['price'] )); - $contentMock->expects($this->any())->method('getSortOrder')->will($this->returnValue( - $linkContentData['sort_order'] + $linkMock->expects($this->any())->method('getSortOrder')->will($this->returnValue( + $linkData['sort_order'] )); - $contentMock->expects($this->any())->method('isShareable')->will($this->returnValue( - $linkContentData['shareable'] + $linkMock->expects($this->any())->method('isShareable')->will($this->returnValue( + $linkData['shareable'] )); - $contentMock->expects($this->any())->method('getNumberOfDownloads')->will($this->returnValue( - $linkContentData['number_of_downloads'] + $linkMock->expects($this->any())->method('getNumberOfDownloads')->will($this->returnValue( + $linkData['number_of_downloads'] )); - $contentMock->expects($this->any())->method('getLinkType')->will($this->returnValue( - $linkContentData['link_type'] + $linkMock->expects($this->any())->method('getLinkType')->will($this->returnValue( + $linkData['link_type'] )); - $contentMock->expects($this->any())->method('getLinkFile')->will($this->returnValue( + $linkMock->expects($this->any())->method('getLinkFile')->will($this->returnValue( $this->linkFileMock )); - if (isset($linkContentData['link_url'])) { - $contentMock->expects($this->any())->method('getLinkUrl')->will($this->returnValue( - $linkContentData['link_url'] + if (isset($linkData['link_url'])) { + $linkMock->expects($this->any())->method('getLinkUrl')->will($this->returnValue( + $linkData['link_url'] )); } - if (isset($linkContentData['sample_url'])) { - $contentMock->expects($this->any())->method('getSampleUrl')->will($this->returnValue( - $linkContentData['sample_url'] + if (isset($linkData['sample_url'])) { + $linkMock->expects($this->any())->method('getSampleUrl')->will($this->returnValue( + $linkData['sample_url'] )); } - if (isset($linkContentData['sample_type'])) { - $contentMock->expects($this->any())->method('getSampleType')->will($this->returnValue( - $linkContentData['sample_type'] + if (isset($linkData['sample_type'])) { + $linkMock->expects($this->any())->method('getSampleType')->will($this->returnValue( + $linkData['sample_type'] )); } - $contentMock->expects($this->any())->method('getSampleFile')->will($this->returnValue( + if (isset($linkData['link_file_content'])) { + $linkMock->expects($this->any())->method('getLinkFileContent')->willReturn($linkData['link_file_content']); + } + if (isset($linkData['sample_file_content'])) { + $linkMock->expects($this->any())->method('getSampleFileContent') + ->willReturn($linkData['sample_file_content']); + } + $linkMock->expects($this->any())->method('getSampleFile')->will($this->returnValue( $this->sampleFileMock )); - return $contentMock; + return $linkMock; } } diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php index 06c849f969cd47da2759747c05254ef143d2b759..d4ec184847edcbdbca8feb4e8a08c04f1b664766 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php @@ -128,69 +128,80 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase } /** - * @param array $linkContentData + * @param array $linkData * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function getLinkContentMock(array $linkContentData) + protected function getLinkMock(array $linkData) { - $contentMock = $this->getMock( - '\Magento\Downloadable\Api\Data\LinkContentInterface', + $linkMock = $this->getMock( + '\Magento\Downloadable\Api\Data\LinkInterface', [], [], '', false ); - $contentMock->expects($this->any())->method('getPrice')->will( + if (isset($linkData['id'])) { + $linkMock->expects($this->any())->method('getId')->willReturn($linkData['id']); + } + + $linkMock->expects($this->any())->method('getPrice')->will( $this->returnValue( - $linkContentData['price'] + $linkData['price'] ) ); - $contentMock->expects($this->any())->method('getTitle')->will( + $linkMock->expects($this->any())->method('getTitle')->will( $this->returnValue( - $linkContentData['title'] + $linkData['title'] ) ); - $contentMock->expects($this->any())->method('getSortOrder')->will( + $linkMock->expects($this->any())->method('getSortOrder')->will( $this->returnValue( - $linkContentData['sort_order'] + $linkData['sort_order'] ) ); - $contentMock->expects($this->any())->method('getNumberOfDownloads')->will( + $linkMock->expects($this->any())->method('getNumberOfDownloads')->will( $this->returnValue( - $linkContentData['number_of_downloads'] + $linkData['number_of_downloads'] ) ); - $contentMock->expects($this->any())->method('isShareable')->will( + $linkMock->expects($this->any())->method('getIsShareable')->will( $this->returnValue( - $linkContentData['shareable'] + $linkData['is_shareable'] ) ); - if (isset($linkContentData['link_type'])) { - $contentMock->expects($this->any())->method('getLinkType')->will( + if (isset($linkData['link_type'])) { + $linkMock->expects($this->any())->method('getLinkType')->will( $this->returnValue( - $linkContentData['link_type'] + $linkData['link_type'] ) ); } - if (isset($linkContentData['link_url'])) { - $contentMock->expects($this->any())->method('getLinkUrl')->will( + if (isset($linkData['link_url'])) { + $linkMock->expects($this->any())->method('getLinkUrl')->will( $this->returnValue( - $linkContentData['link_url'] + $linkData['link_url'] ) ); } - return $contentMock; + if (isset($linkData['link_file'])) { + $linkMock->expects($this->any())->method('getLinkFile')->will( + $this->returnValue( + $linkData['link_file'] + ) + ); + } + return $linkMock; } public function testCreate() { $productSku = 'simple'; - $linkContentData = [ + $linkData = [ 'title' => 'Title', 'sort_order' => 1, 'price' => 10.1, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_type' => 'url', 'link_url' => 'http://example.com/', @@ -198,8 +209,8 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); $this->productMock->expects($this->any())->method('getTypeId')->will($this->returnValue('downloadable')); - $linkContentMock = $this->getLinkContentMock($linkContentData); - $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkContentMock) + $linkMock = $this->getLinkMock($linkData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkMock) ->will($this->returnValue(true)); $this->productMock->expects($this->once())->method('setDownloadableData')->with( @@ -208,19 +219,20 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase [ 'link_id' => 0, 'is_delete' => 0, - 'type' => $linkContentData['link_type'], - 'sort_order' => $linkContentData['sort_order'], - 'title' => $linkContentData['title'], - 'price' => $linkContentData['price'], - 'number_of_downloads' => $linkContentData['number_of_downloads'], - 'is_shareable' => $linkContentData['shareable'], - 'link_url' => $linkContentData['link_url'], + 'type' => $linkData['link_type'], + 'sort_order' => $linkData['sort_order'], + 'title' => $linkData['title'], + 'price' => $linkData['price'], + 'number_of_downloads' => $linkData['number_of_downloads'], + 'is_shareable' => $linkData['is_shareable'], + 'link_url' => $linkData['link_url'], ], ], ] ); - $this->productMock->expects($this->once())->method('save'); - $this->service->save($productSku, $linkContentMock, null); + $this->productTypeMock->expects($this->once())->method('save') + ->with($this->productMock); + $this->service->save($productSku, $linkMock); } /** @@ -230,12 +242,12 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase public function testCreateThrowsExceptionIfTitleIsEmpty() { $productSku = 'simple'; - $linkContentData = [ + $linkData = [ 'title' => '', 'sort_order' => 1, 'price' => 10.1, 'number_of_downloads' => 100, - 'shareable' => true, + 'is_shareable' => true, 'link_type' => 'url', 'link_url' => 'http://example.com/', ]; @@ -243,13 +255,13 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase $this->productMock->expects($this->any())->method('getTypeId')->will($this->returnValue('downloadable')); $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); - $linkContentMock = $this->getLinkContentMock($linkContentData); - $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkContentMock) + $linkMock = $this->getLinkMock($linkData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkMock) ->will($this->returnValue(true)); $this->productMock->expects($this->never())->method('save'); - $this->service->save($productSku, $linkContentMock, null); + $this->service->save($productSku, $linkMock); } public function testUpdate() @@ -258,12 +270,15 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase $linkId = 1; $productSku = 'simple'; $productId = 1; - $linkContentData = [ + $linkData = [ + 'id' => $linkId, 'title' => 'Updated Title', 'sort_order' => 1, 'price' => 10.1, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, + 'link_type' => 'url', + 'link_url' => 'http://example.com/', ]; $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); @@ -271,54 +286,126 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase $storeMock = $this->getMock('\Magento\Store\Model\Store', [], [], '', false); $storeMock->expects($this->any())->method('getWebsiteId')->will($this->returnValue($websiteId)); $this->productMock->expects($this->any())->method('getStore')->will($this->returnValue($storeMock)); - $linkMock = $this->getMock( + $existingLinkMock = $this->getMock( '\Magento\Downloadable\Model\Link', [ '__wakeup', - 'setTitle', - 'setPrice', - 'setSortOrder', - 'setIsShareable', - 'setNumberOfDownloads', 'getId', - 'setProductId', - 'setStoreId', - 'setWebsiteId', - 'setProductWebsiteIds', 'load', - 'save', 'getProductId' ], [], '', false ); - $this->linkFactoryMock->expects($this->once())->method('create')->will($this->returnValue($linkMock)); - $linkContentMock = $this->getLinkContentMock($linkContentData); - $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkContentMock) + $this->linkFactoryMock->expects($this->once())->method('create')->will($this->returnValue($existingLinkMock)); + $linkMock = $this->getLinkMock($linkData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkMock) ->will($this->returnValue(true)); - $linkMock->expects($this->any())->method('getId')->will($this->returnValue($linkId)); - $linkMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); - $linkMock->expects($this->once())->method('load')->with($linkId)->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setTitle')->with($linkContentData['title']) - ->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setSortOrder')->with($linkContentData['sort_order']) - ->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setPrice')->with($linkContentData['price']) - ->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setIsShareable')->with($linkContentData['shareable']) - ->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setNumberOfDownloads')->with($linkContentData['number_of_downloads']) - ->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setProductId')->with($productId) - ->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setStoreId')->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setWebsiteId')->with($websiteId)->will($this->returnSelf()); - $linkMock->expects($this->once())->method('setProductWebsiteIds')->will($this->returnSelf()); - $linkMock->expects($this->once())->method('save')->will($this->returnSelf()); - - $this->assertEquals($linkId, $this->service->save($productSku, $linkContentMock, $linkId)); + $existingLinkMock->expects($this->any())->method('getId')->will($this->returnValue($linkId)); + $existingLinkMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); + $existingLinkMock->expects($this->once())->method('load')->with($linkId)->will($this->returnSelf()); + + $this->productMock->expects($this->once())->method('setDownloadableData')->with( + [ + 'link' => [ + [ + 'link_id' => $linkId, + 'is_delete' => 0, + 'type' => $linkData['link_type'], + 'sort_order' => $linkData['sort_order'], + 'title' => $linkData['title'], + 'price' => $linkData['price'], + 'number_of_downloads' => $linkData['number_of_downloads'], + 'is_shareable' => $linkData['is_shareable'], + 'link_url' => $linkData['link_url'], + ], + ], + ] + ); + $this->productTypeMock->expects($this->once())->method('save') + ->with($this->productMock); + + $this->assertEquals($linkId, $this->service->save($productSku, $linkMock)); + } + + public function testUpdateWithExistingFile() + { + $websiteId = 1; + $linkId = 1; + $productSku = 'simple'; + $productId = 1; + $linkFile = '/l/i/link.jpg'; + $encodedFiles = "something"; + $linkData = [ + 'id' => $linkId, + 'title' => 'Updated Title', + 'sort_order' => 1, + 'price' => 10.1, + 'is_shareable' => true, + 'number_of_downloads' => 100, + 'link_type' => 'file', + 'link_file' => $linkFile, + ]; + $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) + ->will($this->returnValue($this->productMock)); + $this->productMock->expects($this->any())->method('getId')->will($this->returnValue($productId)); + $storeMock = $this->getMock('\Magento\Store\Model\Store', [], [], '', false); + $storeMock->expects($this->any())->method('getWebsiteId')->will($this->returnValue($websiteId)); + $this->productMock->expects($this->any())->method('getStore')->will($this->returnValue($storeMock)); + $existingLinkMock = $this->getMock( + '\Magento\Downloadable\Model\Link', + [ + '__wakeup', + 'getId', + 'load', + 'getProductId' + ], + [], + '', + false + ); + $this->linkFactoryMock->expects($this->once())->method('create')->will($this->returnValue($existingLinkMock)); + $linkMock = $this->getLinkMock($linkData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkMock) + ->will($this->returnValue(true)); + + $existingLinkMock->expects($this->any())->method('getId')->will($this->returnValue($linkId)); + $existingLinkMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); + $existingLinkMock->expects($this->once())->method('load')->with($linkId)->will($this->returnSelf()); + + $this->jsonEncoderMock->expects($this->once()) + ->method('encode') + ->with( + [ + [ + 'file' => $linkFile, + 'status' => 'old' + ] + ] + )->willReturn($encodedFiles); + $this->productMock->expects($this->once())->method('setDownloadableData')->with( + [ + 'link' => [ + [ + 'link_id' => $linkId, + 'is_delete' => 0, + 'type' => $linkData['link_type'], + 'sort_order' => $linkData['sort_order'], + 'title' => $linkData['title'], + 'price' => $linkData['price'], + 'number_of_downloads' => $linkData['number_of_downloads'], + 'is_shareable' => $linkData['is_shareable'], + 'file' => $encodedFiles, + ], + ], + ] + ); + $this->productTypeMock->expects($this->once())->method('save') + ->with($this->productMock); + + $this->assertEquals($linkId, $this->service->save($productSku, $linkMock)); } /** @@ -330,34 +417,34 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase $linkId = 1; $productSku = 'simple'; $productId = 1; - $linkContentData = [ + $linkData = [ + 'id' => $linkId, 'title' => '', 'sort_order' => 1, 'price' => 10.1, 'number_of_downloads' => 100, - 'shareable' => true, + 'is_shareable' => true, ]; $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); $this->productMock->expects($this->any())->method('getId')->will($this->returnValue($productId)); - $linkMock = $this->getMock( + $existingLinkMock = $this->getMock( '\Magento\Downloadable\Model\Link', ['__wakeup', 'getId', 'load', 'save', 'getProductId'], [], '', false ); - $linkMock->expects($this->any())->method('getId')->will($this->returnValue($linkId)); - $linkMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); - $linkMock->expects($this->once())->method('load')->with($linkId)->will($this->returnSelf()); - $this->linkFactoryMock->expects($this->once())->method('create')->will($this->returnValue($linkMock)); - $linkContentMock = $this->getLinkContentMock($linkContentData); + $existingLinkMock->expects($this->any())->method('getId')->will($this->returnValue($linkId)); + $existingLinkMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); + $existingLinkMock->expects($this->once())->method('load')->with($linkId)->will($this->returnSelf()); + $this->linkFactoryMock->expects($this->once())->method('create')->will($this->returnValue($existingLinkMock)); + $linkContentMock = $this->getLinkMock($linkData); $this->contentValidatorMock->expects($this->any())->method('isValid')->with($linkContentMock) ->will($this->returnValue(true)); - $linkMock->expects($this->never())->method('save'); - - $this->service->save($productSku, $linkContentMock, $linkId, true); + $this->productTypeMock->expects($this->never())->method('save'); + $this->service->save($productSku, $linkContentMock, true); } public function testDelete() diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/ObserverTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/ObserverTest.php index 99fb7ed07618d23e136ce710af5ddb93010b97aa..f372aaa2451400888c72491ba1607e751d69dc0a 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/ObserverTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/ObserverTest.php @@ -497,6 +497,33 @@ class ObserverTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('\Magento\Downloadable\Model\Observer', $result); } + public function testSaveDownloadableOrderItemNotDownloadableItem() + { + $itemId = 100; + $itemMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Item') + ->disableOriginalConstructor() + ->getMock(); + $itemMock->expects($this->any()) + ->method('getId') + ->willReturn($itemId); + $itemMock->expects($this->any()) + ->method('getProductType') + ->willReturn('simple'); + $itemMock->expects($this->never()) + ->method('getProduct'); + $event = new \Magento\Framework\Object( + [ + 'item' => $itemMock, + ] + ); + $observer = new \Magento\Framework\Object( + [ + 'event' => $event + ] + ); + $this->observer->saveDownloadableOrderItem($observer); + } + /** * @param $id * @param int $statusId diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AfterProductLoadTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AfterProductLoadTest.php new file mode 100644 index 0000000000000000000000000000000000000000..36f21e6fb5f28382cca4f4bec106d5772d125ec2 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AfterProductLoadTest.php @@ -0,0 +1,220 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\Downloadable\Test\Unit\Model\Plugin; + +class AfterProductLoadTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Downloadable\Model\Plugin\AfterProductLoad + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $linkRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionFactory; + + protected function setUp() + { + $this->linkRepositoryMock = $this->getMock('\Magento\Downloadable\Api\LinkRepositoryInterface'); + $this->productExtensionFactory = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtensionFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->model = new \Magento\Downloadable\Model\Plugin\AfterProductLoad( + $this->linkRepositoryMock, + $this->productExtensionFactory + ); + $this->productMock = $this->getMockBuilder('\Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + $this->productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['setDownloadableProductLinks', 'setDownloadableProductSamples'])->getMock(); + } + + public function testAfterLoad() + { + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + + $this->productExtensionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->productExtensionMock); + + $linkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $this->linkRepositoryMock->expects($this->once()) + ->method('getLinksByProduct') + ->with($this->productMock) + ->willReturn([$linkMock]); + $sampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $this->linkRepositoryMock->expects($this->once()) + ->method('getSamplesByProduct') + ->with($this->productMock) + ->willReturn([$sampleMock]); + $this->productExtensionMock->expects($this->once()) + ->method('setDownloadableProductLinks') + ->with([$linkMock]) + ->willReturnSelf(); + $this->productExtensionMock->expects($this->once()) + ->method('setDownloadableProductSamples') + ->with([$sampleMock]) + ->willReturnSelf(); + $this->productMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($this->productExtensionMock) + ->willReturnSelf(); + + $this->assertEquals( + $this->productMock, + $this->model->afterLoad($this->productMock) + ); + } + + public function testAfterLoadWithExistingExtensionAttributes() + { + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + + $this->productExtensionFactory->expects($this->never()) + ->method('create'); + + $linkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $this->linkRepositoryMock->expects($this->once()) + ->method('getLinksByProduct') + ->with($this->productMock) + ->willReturn([$linkMock]); + $sampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $this->linkRepositoryMock->expects($this->once()) + ->method('getSamplesByProduct') + ->with($this->productMock) + ->willReturn([$sampleMock]); + $this->productExtensionMock->expects($this->once()) + ->method('setDownloadableProductLinks') + ->with([$linkMock]) + ->willReturnSelf(); + $this->productExtensionMock->expects($this->once()) + ->method('setDownloadableProductSamples') + ->with([$sampleMock]) + ->willReturnSelf(); + $this->productMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($this->productExtensionMock) + ->willReturnSelf(); + + $this->assertEquals( + $this->productMock, + $this->model->afterLoad($this->productMock) + ); + } + + public function testAfterLoadOnlyLinks() + { + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + + $this->productExtensionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->productExtensionMock); + + $linkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $this->linkRepositoryMock->expects($this->once()) + ->method('getLinksByProduct') + ->with($this->productMock) + ->willReturn([$linkMock]); + $this->linkRepositoryMock->expects($this->once()) + ->method('getSamplesByProduct') + ->with($this->productMock) + ->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('setDownloadableProductLinks') + ->with([$linkMock]) + ->willReturnSelf(); + $this->productExtensionMock->expects($this->never()) + ->method('setDownloadableProductSamples'); + $this->productMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($this->productExtensionMock) + ->willReturnSelf(); + + $this->assertEquals( + $this->productMock, + $this->model->afterLoad($this->productMock) + ); + } + + public function testAfterLoadOnlySamples() + { + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + + $this->productExtensionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->productExtensionMock); + + $this->linkRepositoryMock->expects($this->once()) + ->method('getLinksByProduct') + ->with($this->productMock) + ->willReturn(null); + $sampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $this->linkRepositoryMock->expects($this->once()) + ->method('getSamplesByProduct') + ->with($this->productMock) + ->willReturn([$sampleMock]); + $this->productExtensionMock->expects($this->never()) + ->method('setDownloadableProductLinks'); + $this->productExtensionMock->expects($this->once()) + ->method('setDownloadableProductSamples') + ->with([$sampleMock]) + ->willReturnSelf(); + $this->productMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($this->productExtensionMock) + ->willReturnSelf(); + + $this->assertEquals( + $this->productMock, + $this->model->afterLoad($this->productMock) + ); + } + + public function testAfterLoadIfProductTypeNotDownloadable() + { + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE); + $this->productMock->expects($this->never())->method('getExtensionAttributes'); + $this->productMock->expects($this->never())->method('setExtensionAttributes'); + $this->assertEquals( + $this->productMock, + $this->model->afterLoad($this->productMock) + ); + } +} diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e33241defa659ee03c309c4ca74fe85b237a9b07 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php @@ -0,0 +1,328 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\Downloadable\Test\Unit\Model\Plugin; + +use \Magento\Downloadable\Model\Plugin\AroundProductRepositorySave; + +class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var AroundProductRepositorySave + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $linkRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $sampleRepositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $savedProductMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productExtensionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $existingProductExtensionMock; + + /** + * @var \Closure + */ + protected $closureMock; + + protected function setUp() + { + $this->productRepositoryMock = $this->getMock('Magento\Catalog\Api\ProductRepositoryInterface'); + $this->linkRepositoryMock = $this->getMock('Magento\Downloadable\Api\LinkRepositoryInterface'); + $this->sampleRepositoryMock = $this->getMock('Magento\Downloadable\Api\SampleRepositoryInterface'); + $this->productMock = $this->getMock('\Magento\Catalog\Api\Data\ProductInterface'); + $this->savedProductMock = $this->getMock('\Magento\Catalog\Api\Data\ProductInterface'); + $this->closureMock = function () { + return $this->savedProductMock; + }; + $this->model = new AroundProductRepositorySave( + $this->linkRepositoryMock, + $this->sampleRepositoryMock ); + $this->productExtensionMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['getDownloadableProductLinks', 'getDownloadableProductSamples'])->getMock(); + $this->existingProductExtensionMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductExtension') + ->setMethods(['getDownloadableProductLinks', 'getDownloadableProductSamples']) + ->getMock(); + } + + public function testAroundSaveWhenProductIsSimple() + { + $this->productMock->expects($this->once())->method('getTypeId')->willReturn('simple'); + $this->productMock->expects($this->never())->method('getExtensionAttributes'); + + $this->assertEquals( + $this->savedProductMock, + $this->model->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + public function testAroundSaveWhenProductHasNoExtensionAttributes() + { + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn(null); + + $this->savedProductMock->expects($this->never())->method('getExtensionAttributes'); + $this->linkRepositoryMock->expects($this->never())->method('save'); + + $this->assertEquals( + $this->savedProductMock, + $this->model->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + /** + * Input has two links and two samples, one existing and one new + * Existing product has two links and two samples, one will be updated and one will be deleted + */ + public function testAroundSave() + { + $productSku = "downloadable_product"; + $existingLinkId = '2'; + $existingSampleId = '5'; + $toBeDeletedLinkId = '3'; + $toBeDeletedSampleId = '4'; + + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $updateLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $updateLinkMock->expects($this->once())->method('getId')->willReturn($existingLinkId); + $newLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $newLinkMock->expects($this->once())->method('getId')->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getDownloadableProductLinks') + ->willReturn([$newLinkMock, $updateLinkMock]); + + $updateSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $updateSampleMock->expects($this->once())->method('getId')->willReturn($existingSampleId); + $newSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $newSampleMock->expects($this->once())->method('getId')->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getDownloadableProductSamples') + ->willReturn([$updateSampleMock, $newSampleMock]); + + $existingLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $existingLinkMock->expects($this->once())->method('getId')->willReturn($existingLinkId); + $toBeDeletedLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $toBeDeletedLinkMock->expects($this->once())->method('getId')->willReturn($toBeDeletedLinkId); + + $existingSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $existingSampleMock->expects($this->once())->method('getId')->willReturn($existingSampleId); + $toBeDeletedSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $toBeDeletedSampleMock->expects($this->once())->method('getId')->willReturn($toBeDeletedSampleId); + + $this->savedProductMock->expects($this->any())->method('getSku')->willReturn($productSku); + $this->savedProductMock->expects($this->exactly(2))->method('getExtensionAttributes') + ->willReturn($this->existingProductExtensionMock); + $this->existingProductExtensionMock->expects($this->once()) + ->method('getDownloadableProductLinks') + ->willReturn([$existingLinkMock, $toBeDeletedLinkMock]); + $this->existingProductExtensionMock->expects($this->once()) + ->method('getDownloadableProductSamples') + ->willReturn([$existingSampleMock, $toBeDeletedSampleMock]); + + $this->linkRepositoryMock->expects($this->at(0)) + ->method('save') + ->with($productSku, $updateLinkMock); + $this->linkRepositoryMock->expects($this->at(1)) + ->method('save') + ->with($productSku, $newLinkMock); + $this->linkRepositoryMock->expects($this->at(2)) + ->method('delete') + ->with($toBeDeletedLinkId); + + $this->sampleRepositoryMock->expects($this->at(0)) + ->method('save') + ->with($productSku, $updateSampleMock); + $this->sampleRepositoryMock->expects($this->at(1)) + ->method('save') + ->with($productSku, $newSampleMock); + $this->sampleRepositoryMock->expects($this->at(2)) + ->method('delete') + ->with($toBeDeletedSampleId); + + $newProductMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface') + ->disableOriginalConstructor()->getMock(); + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku, false, null, true) + ->willReturn($newProductMock); + + $this->assertEquals( + $newProductMock, + $this->model->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + /** + * Input has two links and no samples, one existing and one new + * Existing product has two links, one will be updated and one will be deleted + */ + public function testAroundSaveWithOnlyLinks() + { + $productSku = "downloadable_product"; + $existingLinkId = '2'; + $toBeDeletedLinkId = '3'; + + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $updateLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $updateLinkMock->expects($this->once())->method('getId')->willReturn($existingLinkId); + $newLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $newLinkMock->expects($this->once())->method('getId')->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getDownloadableProductLinks') + ->willReturn([$newLinkMock, $updateLinkMock]); + + $this->productExtensionMock->expects($this->once()) + ->method('getDownloadableProductSamples') + ->willReturn(null); + + $existingLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $existingLinkMock->expects($this->once())->method('getId')->willReturn($existingLinkId); + $toBeDeletedLinkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $toBeDeletedLinkMock->expects($this->once())->method('getId')->willReturn($toBeDeletedLinkId); + + $this->savedProductMock->expects($this->any())->method('getSku')->willReturn($productSku); + $this->savedProductMock->expects($this->once())->method('getExtensionAttributes') + ->willReturn($this->existingProductExtensionMock); + $this->existingProductExtensionMock->expects($this->once()) + ->method('getDownloadableProductLinks') + ->willReturn([$existingLinkMock, $toBeDeletedLinkMock]); + $this->existingProductExtensionMock->expects($this->never()) + ->method('getDownloadableProductSamples'); + + $this->linkRepositoryMock->expects($this->at(0)) + ->method('save') + ->with($productSku, $updateLinkMock); + $this->linkRepositoryMock->expects($this->at(1)) + ->method('save') + ->with($productSku, $newLinkMock); + $this->linkRepositoryMock->expects($this->at(2)) + ->method('delete') + ->with($toBeDeletedLinkId); + + $this->sampleRepositoryMock->expects($this->never()) + ->method('save'); + + $newProductMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface') + ->disableOriginalConstructor()->getMock(); + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku, false, null, true) + ->willReturn($newProductMock); + + $this->assertEquals( + $newProductMock, + $this->model->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } + + /** + * Input has two samples, one existing and one new + * Existing product has two samples, one will be updated and one will be deleted + */ + public function testAroundSaveWithOnlySamples() + { + $productSku = "downloadable_product"; + $existingSampleId = '5'; + $toBeDeletedSampleId = '4'; + + $this->productMock->expects($this->once())->method('getTypeId') + ->willReturn(\Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE); + $this->productMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->productExtensionMock); + $this->productExtensionMock->expects($this->once()) + ->method('getDownloadableProductLinks') + ->willReturn(null); + + $updateSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $updateSampleMock->expects($this->once())->method('getId')->willReturn($existingSampleId); + $newSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $newSampleMock->expects($this->once())->method('getId')->willReturn(null); + $this->productExtensionMock->expects($this->once()) + ->method('getDownloadableProductSamples') + ->willReturn([$updateSampleMock, $newSampleMock]); + + $existingSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $existingSampleMock->expects($this->once())->method('getId')->willReturn($existingSampleId); + $toBeDeletedSampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + $toBeDeletedSampleMock->expects($this->once())->method('getId')->willReturn($toBeDeletedSampleId); + + $this->savedProductMock->expects($this->any())->method('getSku')->willReturn($productSku); + $this->savedProductMock->expects($this->once())->method('getExtensionAttributes') + ->willReturn($this->existingProductExtensionMock); + $this->existingProductExtensionMock->expects($this->never()) + ->method('getDownloadableProductLinks'); + $this->existingProductExtensionMock->expects($this->once()) + ->method('getDownloadableProductSamples') + ->willReturn([$existingSampleMock, $toBeDeletedSampleMock]); + + $this->linkRepositoryMock->expects($this->never()) + ->method('save'); + + $this->sampleRepositoryMock->expects($this->at(0)) + ->method('save') + ->with($productSku, $updateSampleMock); + $this->sampleRepositoryMock->expects($this->at(1)) + ->method('save') + ->with($productSku, $newSampleMock); + $this->sampleRepositoryMock->expects($this->at(2)) + ->method('delete') + ->with($toBeDeletedSampleId); + + $newProductMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface') + ->disableOriginalConstructor()->getMock(); + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku, false, null, true) + ->willReturn($newProductMock); + + $this->assertEquals( + $newProductMock, + $this->model->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock) + ); + } +} diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/Sample/ContentValidatorTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/Sample/ContentValidatorTest.php index 8a94c4b8ba1279711a75d133a7697b5cf49738c5..517563a68cd8b58ee2baba39bf71ca479dd55005 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/Sample/ContentValidatorTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/Sample/ContentValidatorTest.php @@ -51,15 +51,17 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase false ); $this->sampleFileMock = $this->getMock('\Magento\Downloadable\Api\Data\File\ContentInterface'); - $this->validator = new \Magento\Downloadable\Model\Sample\ContentValidator($this->fileValidatorMock, $this->urlValidatorMock); + $this->validator = new ContentValidator($this->fileValidatorMock, $this->urlValidatorMock); } public function testIsValid() { + $sampleFileContentMock = $this->getMock('Magento\Downloadable\Api\Data\File\ContentInterface'); $sampleContentData = [ 'title' => 'Title', 'sort_order' => 1, 'sample_type' => 'file', + 'sample_file_content' => $sampleFileContentMock, ]; $this->fileValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); $this->urlValidatorMock->expects($this->any())->method('isValid')->will($this->returnValue(true)); @@ -103,7 +105,7 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase */ protected function getSampleContentMock(array $sampleContentData) { - $contentMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleContentInterface'); + $contentMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); $contentMock->expects($this->any())->method('getTitle')->will($this->returnValue( $sampleContentData['title'] )); @@ -119,6 +121,10 @@ class ContentValidatorTest extends \PHPUnit_Framework_TestCase $sampleContentData['sample_url'] )); } + if (isset($sampleContentData['sample_file_content'])) { + $contentMock->expects($this->any())->method('getSampleFileContent') + ->willReturn($sampleContentData['sample_file_content']); + } $contentMock->expects($this->any())->method('getSampleFile')->will($this->returnValue( $this->sampleFileMock )); diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php index 4027405e14f5c27eaf84dc245574e21d4a8a156a..7e25af50c3f6b771308ffc0eed2f79b227bd35b6 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php @@ -15,6 +15,11 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $repositoryMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productTypeMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -55,6 +60,7 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase false ); $this->repositoryMock = $this->getMock('\Magento\Catalog\Model\ProductRepository', [], [], '', false); + $this->productTypeMock = $this->getMock('\Magento\Downloadable\Model\Product\Type', [], [], '', false); $this->contentValidatorMock = $this->getMock( 'Magento\Downloadable\Model\Sample\ContentValidator', [], @@ -78,6 +84,7 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase $this->service = new \Magento\Downloadable\Model\SampleRepository( $this->repositoryMock, + $this->productTypeMock, $this->contentValidatorMock, $this->contentUploaderMock, $this->jsonEncoderMock, @@ -86,35 +93,43 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase } /** - * @param array $sampleContentData + * @param array $sampleData * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function getSampleContentMock(array $sampleContentData) + protected function getSampleMock(array $sampleData) { - $contentMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleContentInterface'); + $sampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); - $contentMock->expects($this->any())->method('getTitle')->will($this->returnValue($sampleContentData['title'])); - $contentMock->expects($this->any())->method('getSortOrder')->will($this->returnValue( - $sampleContentData['sort_order'] + if (isset($sampleData['id'])) { + $sampleMock->expects($this->any())->method('getId')->willReturn($sampleData['id']); + } + $sampleMock->expects($this->any())->method('getTitle')->will($this->returnValue($sampleData['title'])); + $sampleMock->expects($this->any())->method('getSortOrder')->will($this->returnValue( + $sampleData['sort_order'] )); - if (isset($sampleContentData['sample_type'])) { - $contentMock->expects($this->any())->method('getSampleType')->will($this->returnValue( - $sampleContentData['sample_type'] + if (isset($sampleData['sample_type'])) { + $sampleMock->expects($this->any())->method('getSampleType')->will($this->returnValue( + $sampleData['sample_type'] + )); + } + if (isset($sampleData['sample_url'])) { + $sampleMock->expects($this->any())->method('getSampleUrl')->will($this->returnValue( + $sampleData['sample_url'] )); } - if (isset($sampleContentData['sample_url'])) { - $contentMock->expects($this->any())->method('getSampleUrl')->will($this->returnValue( - $sampleContentData['sample_url'] + if (isset($sampleData['sample_file'])) { + $sampleMock->expects($this->any())->method('getSampleFile')->will($this->returnValue( + $sampleData['sample_file'] )); } - return $contentMock; + return $sampleMock; } public function testCreate() { $productSku = 'simple'; - $sampleContentData = [ + $sampleData = [ 'title' => 'Title', 'sort_order' => 1, 'sample_type' => 'url', @@ -123,8 +138,8 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); $this->productMock->expects($this->any())->method('getTypeId')->will($this->returnValue('downloadable')); - $sampleContentMock = $this->getSampleContentMock($sampleContentData); - $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleContentMock) + $sampleMock = $this->getSampleMock($sampleData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleMock) ->will($this->returnValue(true)); $this->productMock->expects($this->once())->method('setDownloadableData')->with([ @@ -132,15 +147,15 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase [ 'sample_id' => 0, 'is_delete' => 0, - 'type' => $sampleContentData['sample_type'], - 'sort_order' => $sampleContentData['sort_order'], - 'title' => $sampleContentData['title'], - 'sample_url' => $sampleContentData['sample_url'], + 'type' => $sampleData['sample_type'], + 'sort_order' => $sampleData['sort_order'], + 'title' => $sampleData['title'], + 'sample_url' => $sampleData['sample_url'], ], ], ]); - $this->productMock->expects($this->once())->method('save'); - $this->service->save($productSku, $sampleContentMock, null); + $this->productTypeMock->expects($this->once())->method('save')->with($this->productMock); + $this->service->save($productSku, $sampleMock); } /** @@ -150,7 +165,7 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase public function testCreateThrowsExceptionIfTitleIsEmpty() { $productSku = 'simple'; - $sampleContentData = [ + $sampleData = [ 'title' => '', 'sort_order' => 1, 'sample_type' => 'url', @@ -160,13 +175,13 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); $this->productMock->expects($this->any())->method('getTypeId')->will($this->returnValue('downloadable')); - $sampleContentMock = $this->getSampleContentMock($sampleContentData); - $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleContentMock) + $sampleMock = $this->getSampleMock($sampleData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleMock) ->will($this->returnValue(true)); - $this->productMock->expects($this->never())->method('save'); + $this->productTypeMock->expects($this->never())->method('save'); - $this->service->save($productSku, $sampleContentMock, null); + $this->service->save($productSku, $sampleMock); } public function testUpdate() @@ -174,39 +189,109 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase $sampleId = 1; $productId = 1; $productSku = 'simple'; - $sampleContentData = [ + $sampleData = [ + 'id' => $sampleId, 'title' => 'Updated Title', 'sort_order' => 1, + 'sample_type' => 'url', + 'sample_url' => 'http://example.com/', ]; $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); $this->productMock->expects($this->any())->method('getId')->will($this->returnValue($productId)); - $sampleMock = $this->getMock( + $existingSampleMock = $this->getMock( '\Magento\Downloadable\Model\Sample', - ['__wakeup', 'setTitle', 'setSortOrder', 'getId', 'setProductId', 'setStoreId', - 'load', 'save', 'getProductId'], + ['__wakeup', 'getId', 'load', 'getProductId'], [], '', false ); - $this->sampleFactoryMock->expects($this->once())->method('create')->will($this->returnValue($sampleMock)); - $sampleContentMock = $this->getSampleContentMock($sampleContentData); - $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleContentMock) + $this->sampleFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($existingSampleMock)); + $sampleMock = $this->getSampleMock($sampleData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleMock) ->will($this->returnValue(true)); - $sampleMock->expects($this->any())->method('getId')->will($this->returnValue($sampleId)); - $sampleMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); - $sampleMock->expects($this->once())->method('load')->with($sampleId)->will($this->returnSelf()); - $sampleMock->expects($this->once())->method('setTitle')->with($sampleContentData['title']) - ->will($this->returnSelf()); - $sampleMock->expects($this->once())->method('setSortOrder')->with($sampleContentData['sort_order']) - ->will($this->returnSelf()); - $sampleMock->expects($this->once())->method('setProductId')->with($productId) - ->will($this->returnSelf()); - $sampleMock->expects($this->once())->method('setStoreId')->will($this->returnSelf()); - $sampleMock->expects($this->once())->method('save')->will($this->returnSelf()); - - $this->assertEquals($sampleId, $this->service->save($productSku, $sampleContentMock, $sampleId)); + $existingSampleMock->expects($this->any())->method('getId')->will($this->returnValue($sampleId)); + $existingSampleMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); + $existingSampleMock->expects($this->once())->method('load')->with($sampleId)->will($this->returnSelf()); + + $this->productMock->expects($this->once())->method('setDownloadableData')->with([ + 'sample' => [ + [ + 'sample_id' => $sampleId, + 'is_delete' => 0, + 'type' => $sampleData['sample_type'], + 'sort_order' => $sampleData['sort_order'], + 'title' => $sampleData['title'], + 'sample_url' => $sampleData['sample_url'], + ], + ], + ]); + $this->productTypeMock->expects($this->once())->method('save')->with($this->productMock); + + $this->assertEquals($sampleId, $this->service->save($productSku, $sampleMock)); + } + + public function testUpdateWithExistingFile() + { + $sampleId = 1; + $productId = 1; + $productSku = 'simple'; + $sampleFile = '/s/a/sample.jpg'; + $encodedFile = 'something'; + $sampleData = [ + 'id' => $sampleId, + 'title' => 'Updated Title', + 'sort_order' => 1, + 'sample_type' => 'file', + 'sample_file' => $sampleFile, + ]; + $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) + ->will($this->returnValue($this->productMock)); + $this->productMock->expects($this->any())->method('getId')->will($this->returnValue($productId)); + $existingSampleMock = $this->getMock( + '\Magento\Downloadable\Model\Sample', + ['__wakeup', 'getId', 'load', 'getProductId'], + [], + '', + false + ); + $this->sampleFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($existingSampleMock)); + $sampleMock = $this->getSampleMock($sampleData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleMock) + ->will($this->returnValue(true)); + + $existingSampleMock->expects($this->any())->method('getId')->will($this->returnValue($sampleId)); + $existingSampleMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); + $existingSampleMock->expects($this->once())->method('load')->with($sampleId)->will($this->returnSelf()); + + $this->jsonEncoderMock->expects($this->once()) + ->method('encode') + ->with( + [ + [ + 'file' => $sampleFile, + 'status' => 'old', + ] + ] + )->willReturn($encodedFile); + $this->productMock->expects($this->once())->method('setDownloadableData')->with([ + 'sample' => [ + [ + 'sample_id' => $sampleId, + 'is_delete' => 0, + 'type' => $sampleData['sample_type'], + 'sort_order' => $sampleData['sort_order'], + 'title' => $sampleData['title'], + 'file' => $encodedFile, + ], + ], + ]); + $this->productTypeMock->expects($this->once())->method('save')->with($this->productMock); + + $this->assertEquals($sampleId, $this->service->save($productSku, $sampleMock)); } /** @@ -218,31 +303,33 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase $sampleId = 1; $productSku = 'simple'; $productId = 1; - $sampleContentData = [ + $sampleData = [ + 'id' => $sampleId, 'title' => '', 'sort_order' => 1, ]; $this->repositoryMock->expects($this->any())->method('get')->with($productSku, true) ->will($this->returnValue($this->productMock)); $this->productMock->expects($this->any())->method('getId')->will($this->returnValue($productId)); - $sampleMock = $this->getMock( + $existingSampleMock = $this->getMock( '\Magento\Downloadable\Model\Sample', ['__wakeup', 'getId', 'load', 'save', 'getProductId'], [], '', false ); - $sampleMock->expects($this->any())->method('getId')->will($this->returnValue($sampleId)); - $sampleMock->expects($this->once())->method('load')->with($sampleId)->will($this->returnSelf()); - $sampleMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); - $this->sampleFactoryMock->expects($this->once())->method('create')->will($this->returnValue($sampleMock)); - $sampleContentMock = $this->getSampleContentMock($sampleContentData); - $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleContentMock) + $existingSampleMock->expects($this->any())->method('getId')->will($this->returnValue($sampleId)); + $existingSampleMock->expects($this->once())->method('load')->with($sampleId)->will($this->returnSelf()); + $existingSampleMock->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); + $this->sampleFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($existingSampleMock)); + $sampleMock = $this->getSampleMock($sampleData); + $this->contentValidatorMock->expects($this->any())->method('isValid')->with($sampleMock) ->will($this->returnValue(true)); - $sampleMock->expects($this->never())->method('save'); + $this->productTypeMock->expects($this->never())->method('save'); - $this->service->save($productSku, $sampleContentMock, $sampleId, true); + $this->service->save($productSku, $sampleMock, true); } public function testDelete() diff --git a/app/code/Magento/Downloadable/composer.json b/app/code/Magento/Downloadable/composer.json index 69f7d646d0ffd16100c2deddc801ab123ab375ad..0d193d70b390aec33ca02dc0f4bab3f640a738f0 100644 --- a/app/code/Magento/Downloadable/composer.json +++ b/app/code/Magento/Downloadable/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-wishlist": "0.74.0-beta6", - "magento/module-gift-message": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-msrp": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-wishlist": "0.74.0-beta7", + "magento/module-gift-message": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-msrp": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Downloadable/etc/di.xml b/app/code/Magento/Downloadable/etc/di.xml index 9b492b051acc779329be9e761c9ede86ce6752e7..acb63729a578108f11e7b5f9d59c60d3d1e00745 100644 --- a/app/code/Magento/Downloadable/etc/di.xml +++ b/app/code/Magento/Downloadable/etc/di.xml @@ -58,12 +58,16 @@ </argument> </arguments> </type> + <type name="Magento\Catalog\Model\Product"> + <plugin name="downloadableAfterLoad" type="\Magento\Downloadable\Model\Plugin\AfterProductLoad"/> + </type> + <type name="Magento\Catalog\Api\ProductRepositoryInterface"> + <plugin name="downloadableAroundSave" type="\Magento\Downloadable\Model\Plugin\AroundProductRepositorySave"/> + </type> <preference for="\Magento\Downloadable\Api\LinkRepositoryInterface" type="\Magento\Downloadable\Model\LinkRepository" /> <preference for="\Magento\Downloadable\Api\SampleRepositoryInterface" type="\Magento\Downloadable\Model\SampleRepository" /> <preference for="\Magento\Downloadable\Api\Data\LinkInterface" type="\Magento\Downloadable\Model\Link" /> <preference for="\Magento\Downloadable\Api\Data\SampleInterface" type="\Magento\Downloadable\Model\Sample" /> - <preference for="\Magento\Downloadable\Api\Data\SampleContentInterface" type="\Magento\Downloadable\Model\Sample\Content" /> - <preference for="\Magento\Downloadable\Api\Data\LinkContentInterface" type="\Magento\Downloadable\Model\Link\Content" /> <preference for="\Magento\Downloadable\Api\Data\File\ContentInterface" type="\Magento\Downloadable\Model\File\Content" /> <preference for="\Magento\Downloadable\Api\Data\File\ContentUploaderInterface" type="\Magento\Downloadable\Model\File\ContentUploader" /> <preference for="\Magento\Downloadable\Model\Product\TypeHandler\TypeHandlerInterface" type="\Magento\Downloadable\Model\Product\TypeHandler\TypeHandler" /> diff --git a/app/code/Magento/Downloadable/etc/service_data_attributes.xml b/app/code/Magento/Downloadable/etc/service_data_attributes.xml new file mode 100644 index 0000000000000000000000000000000000000000..80cc1cb0abf9ff457b97d12eddc9b3b6ee519784 --- /dev/null +++ b/app/code/Magento/Downloadable/etc/service_data_attributes.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> + <attribute code="downloadable_product_links" type="Magento\Downloadable\Api\Data\LinkInterface[]" /> + <attribute code="downloadable_product_samples" type="Magento\Downloadable\Api\Data\SampleInterface[]" /> + </extension_attributes> +</config> diff --git a/app/code/Magento/Downloadable/etc/webapi.xml b/app/code/Magento/Downloadable/etc/webapi.xml index 0291fe5322f8328380ab63b58dfd7b8b8322dbe2..7f597119f9e74db7142d3baa866ec3c697c67e45 100644 --- a/app/code/Magento/Downloadable/etc/webapi.xml +++ b/app/code/Magento/Downloadable/etc/webapi.xml @@ -25,13 +25,13 @@ <resource ref="Magento_Downloadable::downloadable" /> </resources> </route> - <route url="/V1/products/:sku/downloadable-links/:linkId" method="PUT"> + <route url="/V1/products/:sku/downloadable-links/:id" method="PUT"> <service class="Magento\Downloadable\Api\LinkRepositoryInterface" method="save"/> <resources> <resource ref="Magento_Downloadable::downloadable" /> </resources> </route> - <route url="/V1/products/downloadable-links/:linkId" method="DELETE"> + <route url="/V1/products/downloadable-links/:id" method="DELETE"> <service class="Magento\Downloadable\Api\LinkRepositoryInterface" method="delete"/> <resources> <resource ref="Magento_Downloadable::downloadable" /> @@ -43,13 +43,13 @@ <resource ref="Magento_Downloadable::downloadable" /> </resources> </route> - <route url="/V1/products/:sku/downloadable-links/samples/:sampleId" method="PUT"> + <route url="/V1/products/:sku/downloadable-links/samples/:id" method="PUT"> <service class="Magento\Downloadable\Api\SampleRepositoryInterface" method="save"/> <resources> <resource ref="Magento_Downloadable::downloadable" /> </resources> </route> - <route url="/V1/products/downloadable-links/samples/:sampleId" method="DELETE"> + <route url="/V1/products/downloadable-links/samples/:id" method="DELETE"> <service class="Magento\Downloadable\Api\SampleRepositoryInterface" method="delete"/> <resources> <resource ref="Magento_Downloadable::downloadable" /> diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml index dada69c3e47a9ba4ee7732276d71affd02ea4667..8196069e692019324ad8295aaa7a6d70be207d0c 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml @@ -39,7 +39,7 @@ <div class="admin__field admin__field-wide"> <div class="admin__field-control"> <div class="admin__control-table-wrapper"> - <table cellspacing="0" class="admin__control-table"> + <table class="admin__control-table"> <thead> <tr> <th class="col-title _required"><span><?php echo __('Title') ?></span></th> @@ -163,7 +163,7 @@ require([ '</td>'+ '<td class="col-sort"><input type="text" name="downloadable[link][<%- data.id %>][sort_order]" value="<%- data.sort_order %>" class="input-text admin__control-text sort" /></td>'+ '<td class="col-action">'+ - '<button id="downloadable_link_<%- data.id %>_delete_button" type="button" class="action-remove"><span><?php echo __('Delete'); ?></span></button>'+ + '<button id="downloadable_link_<%- data.id %>_delete_button" type="button" class="action-delete"><span><?php echo __('Delete'); ?></span></button>'+ '</td>'+ '</tr>'; @@ -310,7 +310,7 @@ require([ } }, bindRemoveButtons : function(){ - var buttons = $$('tbody#link_items_body .action-remove'); + var buttons = $$('tbody#link_items_body .action-delete'); for(var i=0;i<buttons.length;i++){ if(!$(buttons[i]).binded && !$(buttons[i]).hasClassName('disabled')){ $(buttons[i]).binded = true; diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/samples.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/samples.phtml index 82ba490f0cf862ddce3e8a84944e889443979a62..11f7ee94465e6c143b1a6037c5b3ffebd59a21a7 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/samples.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/samples.phtml @@ -31,7 +31,7 @@ $block->getConfigJson(); <div class="admin__field admin__field-wide"> <div class="admin__field-control"> <div class="admin__control-table-wrapper"> - <table cellspacing="0" class="admin__control-table"> + <table class="admin__control-table"> <thead> <tr> <th class="_required col-title"><span><?php echo __('Title') ?></span></th> @@ -102,7 +102,7 @@ require([ '</td>'+ '<td class="col-sort"><input type="text" name="downloadable[sample][<%- data.id %>][sort_order]" value="<%- data.sort_order %>" class="input-text sort admin__control-text" /></td>'+ '<td class="col-actions">'+ - '<button type="button" class="action-remove"><span>Delete</span></button>'+ + '<button type="button" class="action-delete"><span>Delete</span></button>'+ '</td>'+ '</tr>'; sampleItems = { @@ -183,7 +183,7 @@ require([ } }, bindRemoveButtons: function() { - var buttons = $$('tbody#sample_items_body .action-remove'); + var buttons = $$('tbody#sample_items_body .action-delete'); for(var i=0;i<buttons.length;i++){ if(!$(buttons[i]).binded){ $(buttons[i]).binded = true; diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/sales/items/column/downloadable/name.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/sales/items/column/downloadable/name.phtml index 79f67d109af865df0a47bcb29e0003d86b152c83..aa6712c6d459d0938ff92651aa3516465aa69039 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/sales/items/column/downloadable/name.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/sales/items/column/downloadable/name.phtml @@ -10,11 +10,14 @@ <?php if ($_item = $block->getItem()): ?> <div class="product-title"><?php echo $_item->getName() ?></div> - <div><strong><?php echo __('SKU') ?>:</strong> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($block->getSku()))); ?></div> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> + <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($block->getSku()))); ?> + </div> <?php if ($block->getOrderOptions()): ?> <dl class="item-options"> <?php foreach ($block->getOrderOptions() as $_option): ?> - <dt><?php echo $_option['label'] ?></dt> + <dt><?php echo $_option['label'] ?>:</dt> <dd> <?php if (isset($_option['custom_view']) && $_option['custom_view']): ?> <?php echo $_option['value'];?> @@ -39,7 +42,7 @@ require(['prototype'], function(){ <?php endif; ?> <?php if ($block->getLinks()): ?> <dl class="item-options"> - <dt><?php echo $block->getLinksTitle(); ?></dt> + <dt><?php echo $block->getLinksTitle(); ?>:</dt> <?php foreach ($block->getLinks()->getPurchasedItems() as $_link): ?> <dd><?php echo $block->escapeHtml($_link->getLinkTitle()) ?> (<?php echo $_link->getNumberOfDownloadsUsed() . ' / ' . ($_link->getNumberOfDownloadsBought() ? $_link->getNumberOfDownloadsBought() : __('U')) ?>)</dd> <?php endforeach; ?> diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index ac8c5805f4b72f8727d09a4a4cbc71a0f05c2258..c8fa8214eab58921da003c19e9a5c55b4a3d66c1 100755 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -31,14 +31,14 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract /** * Read connection * - * @var \Magento\Framework\DB\Adapter\Pdo\Mysql + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql | string */ protected $_read; /** * Write connection * - * @var \Magento\Framework\DB\Adapter\Pdo\Mysql + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql | string */ protected $_write; diff --git a/app/code/Magento/Eav/composer.json b/app/code/Magento/Eav/composer.json index 48ba714ad64dafc7360bb73aa31e87ac3a96ac0d..b67c368db4d0263cd85abde008a6fdae9063b397 100644 --- a/app/code/Magento/Eav/composer.json +++ b/app/code/Magento/Eav/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Eav/etc/di.xml b/app/code/Magento/Eav/etc/di.xml index 3dfebf456c7ff4ae26f6f8a118431872c7c2f67e..00524114f784dd3bc859a8395a9c1d23012433cc 100644 --- a/app/code/Magento/Eav/etc/di.xml +++ b/app/code/Magento/Eav/etc/di.xml @@ -57,4 +57,9 @@ </argument> </arguments> </type> + <type name="Magento\Eav\Model\Entity\Attribute"> + <arguments> + <argument name="reservedAttributeList" xsi:type="object">Magento\Catalog\Model\Product\ReservedAttributeList\Proxy</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Email/Model/BackendTemplate.php b/app/code/Magento/Email/Model/BackendTemplate.php index be5b232564a67e139724e96f6d7a51a89702ed9c..c8bc6b34398e0c492f9123cfaeedc8182da23299 100644 --- a/app/code/Magento/Email/Model/BackendTemplate.php +++ b/app/code/Magento/Email/Model/BackendTemplate.php @@ -5,6 +5,8 @@ */ namespace Magento\Email\Model; +use Magento\Framework\App\Config\ScopeConfigInterface; + /** * Adminhtml email template model * @@ -78,7 +80,7 @@ class BackendTemplate extends Template return []; } - $configData = $this->_scopeConfig->getValue(null, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT); + $configData = $this->_scopeConfig->getValue(null, ScopeConfigInterface::SCOPE_TYPE_DEFAULT); $paths = $this->_findEmailTemplateUsages($templateCode, $configData, ''); return $paths; } diff --git a/app/code/Magento/Email/composer.json b/app/code/Magento/Email/composer.json index afc6d37eb433e3b75b32196ad86b641530dbb796..1a17463f5c6eaecae56d40b2f087b987c1ec1d23 100644 --- a/app/code/Magento/Email/composer.json +++ b/app/code/Magento/Email/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-variable": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-variable": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Fedex/composer.json b/app/code/Magento/Fedex/composer.json index 4e2b254631e2af230d799ecfca6b01371e26afcf..2fa84179799528959e83982cfd815454ce43f311 100644 --- a/app/code/Magento/Fedex/composer.json +++ b/app/code/Magento/Fedex/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GiftMessage/composer.json b/app/code/Magento/GiftMessage/composer.json index 68ce2c1de0918b500fa744563995ea560aa00240..b7da7641a3318d3952c2c24a75fa491fe886c920 100644 --- a/app/code/Magento/GiftMessage/composer.json +++ b/app/code/Magento/GiftMessage/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-multishipping": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-multishipping": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GiftMessage/etc/data_object.xml b/app/code/Magento/GiftMessage/etc/service_data_attributes.xml similarity index 64% rename from app/code/Magento/GiftMessage/etc/data_object.xml rename to app/code/Magento/GiftMessage/etc/service_data_attributes.xml index a1255cc8a161a5a8d28090697088a87ede8920e7..f02c0a717e169224d0b7d450e861f38d7176dc7f 100644 --- a/app/code/Magento/GiftMessage/etc/data_object.xml +++ b/app/code/Magento/GiftMessage/etc/service_data_attributes.xml @@ -5,11 +5,11 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Sales\Api\Data\OrderInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Sales\Api\Data\OrderInterface"> <attribute code="gift_message" type="Magento\GiftMessage\Api\Data\MessageInterface" /> - </custom_attributes> - <custom_attributes for="Magento\Sales\Api\Data\OrderItemInterface"> + </extension_attributes> + <extension_attributes for="Magento\Sales\Api\Data\OrderItemInterface"> <attribute code="gift_message" type="Magento\GiftMessage\Api\Data\MessageInterface" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/app/code/Magento/GiftMessage/view/adminhtml/templates/sales/order/create/giftoptions.phtml b/app/code/Magento/GiftMessage/view/adminhtml/templates/sales/order/create/giftoptions.phtml index 3b6710cb9e1450263c494d2ee40e9860b66a4a69..b810ccccd95d8f23085677614fd4b2279705688c 100644 --- a/app/code/Magento/GiftMessage/view/adminhtml/templates/sales/order/create/giftoptions.phtml +++ b/app/code/Magento/GiftMessage/view/adminhtml/templates/sales/order/create/giftoptions.phtml @@ -12,8 +12,8 @@ <?php if ($_item): ?> <?php $_childHtml = trim($block->getChildHtml('', false));?> <?php if ($_childHtml): ?> - <tr class="border"> - <td colspan="8"> + <tr class="row-gift-options"> + <td colspan="7"> <a class="action-link" href="#" id="gift_options_link_<?php echo $_item->getId() ?>"><?php echo __('Gift Options') ?></a> <script> require([ diff --git a/app/code/Magento/GoogleAdwords/composer.json b/app/code/Magento/GoogleAdwords/composer.json index 81dcd88401f817917d78a4ef6c7662e1cef9e6b8..3aa69ec189227a3ebce792f590d80dc771b01a15 100644 --- a/app/code/Magento/GoogleAdwords/composer.json +++ b/app/code/Magento/GoogleAdwords/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GoogleAdwords/etc/di.xml b/app/code/Magento/GoogleAdwords/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..293db157d7c38cca198df46a541016f71c97dd54 --- /dev/null +++ b/app/code/Magento/GoogleAdwords/etc/di.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> + <type name="Magento\GoogleAdwords\Model\Observer"> + <arguments> + <argument name="collection" xsi:type="object">Magento\Sales\Model\Resource\Order\Collection\Proxy</argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/GoogleAnalytics/composer.json b/app/code/Magento/GoogleAnalytics/composer.json index 68cfa226900d210e823aae6eb94a46500ba21fd0..3a46c54505deea1536e2d8b0fc8ac690f9448633 100644 --- a/app/code/Magento/GoogleAnalytics/composer.json +++ b/app/code/Magento/GoogleAnalytics/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-cookie": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-cookie": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GoogleOptimizer/composer.json b/app/code/Magento/GoogleOptimizer/composer.json index a20b62e29cb95b1840d2dfc056c0e6df5b9638a2..5ef9e22e90d5654ee85e50d05e854b7319f48cdb 100644 --- a/app/code/Magento/GoogleOptimizer/composer.json +++ b/app/code/Magento/GoogleOptimizer/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-google-analytics": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-google-analytics": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items.php index 1a7253c6c788cf98453a2221537b92fcc7992cae..0ec30477e3866e7d7582241f0892d6fa860d67d1 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items.php @@ -7,12 +7,10 @@ namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping; use Magento\Backend\App\Action; use Magento\Framework\Notification\NotifierInterface; +use Magento\Framework\Controller\ResultFactory; /** * GoogleShopping Admin Items Controller - * - * @name \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Items - * @author Magento Core Team <core@magentocommerce.com> */ class Items extends \Magento\Backend\App\Action { @@ -55,7 +53,7 @@ class Items extends \Magento\Backend\App\Action * Redirect user to Google Captcha challenge * * @param \Zend_Gdata_App_CaptchaRequiredException $e - * @return void + * @return \Magento\Framework\Controller\ResultInterface */ protected function _redirectToCaptcha($e) { @@ -68,12 +66,13 @@ class Items extends \Magento\Backend\App\Action ] ); if ($this->getRequest()->isAjax()) { - $this->getResponse()->representJson( - $this->_objectManager->get('Magento\Framework\Json\Helper\Data') - ->jsonEncode(['redirect' => $redirectUrl]) - ); + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + return $resultJson->setData(['redirect' => $redirectUrl]); } else { - $this->_redirect($redirectUrl); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + return $resultRedirect->setUrl($redirectUrl); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php index ab9061908528a8d2cc1786b291096e190ae97702..ef6a9807e247bfe195da7c0aad055eb0e1a821ff 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -35,39 +34,34 @@ class ConfirmCaptcha extends \Magento\GoogleShopping\Controller\Adminhtml\Google /** * Confirm CAPTCHA * - * @return void + * @return \Magento\Framework\Controller\ResultInterface */ public function execute() { $storeId = $this->_getStore()->getId(); try { - $this->_objectManager->create( - 'Magento\GoogleShopping\Model\Service' - )->getClient( - $storeId, - $this->urlDecoder->decode( - $this->getRequest()->getParam('captcha_token') - ), - $this->getRequest()->getParam('user_confirm') - ); + $this->_objectManager->create('Magento\GoogleShopping\Model\Service') + ->getClient( + $storeId, + $this->urlDecoder->decode($this->getRequest()->getParam('captcha_token')), + $this->getRequest()->getParam('user_confirm') + ); $this->messageManager->addSuccess(__('Captcha has been confirmed.')); } catch (\Zend_Gdata_App_CaptchaRequiredException $e) { $this->messageManager->addError(__('There was a Captcha confirmation error: %1', $e->getMessage())); - $this->_redirectToCaptcha($e); - return; + return $this->_redirectToCaptcha($e); } catch (\Zend_Gdata_App_Exception $e) { $this->messageManager->addError( - $this->_objectManager->get( - 'Magento\GoogleShopping\Helper\Data' - )->parseGdataExceptionMessage( - $e->getMessage() - ) + $this->_objectManager->get('Magento\GoogleShopping\Helper\Data') + ->parseGdataExceptionMessage($e->getMessage()) ); } catch (\Exception $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->messageManager->addError(__('Something went wrong during Captcha confirmation.')); } - $this->_redirect('adminhtml/*/index', ['store' => $storeId]); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT); + return $resultRedirect->setPath('adminhtml/*/index', ['store' => $storeId]); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Grid.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Grid.php index 7bd43f98baa86da153c1ad3984d05720acdef6f1..c0565fd7d89b67cbf1ce1bbee6eef31180fdd0d8 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Grid.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Grid.php @@ -6,22 +6,43 @@ */ namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Items; +use Magento\Backend\App\Action; +use Magento\Framework\Notification\NotifierInterface; + class Grid extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Items { + /** + * @var \Magento\Framework\View\LayoutFactory + */ + protected $layoutFactory; + + /** + * @param Action\Context $context + * @param NotifierInterface $notifier + * @param \Magento\Framework\Url\EncoderInterface $urlEncoder + * @param \Magento\Framework\View\LayoutFactory $layoutFactory + */ + public function __construct( + Action\Context $context, + NotifierInterface $notifier, + \Magento\Framework\Url\EncoderInterface $urlEncoder, + \Magento\Framework\View\LayoutFactory $layoutFactory + ) { + $this->layoutFactory = $layoutFactory; + parent::__construct($context, $notifier, $urlEncoder); + } + /** * Grid with Google Content items * - * @return void + * @return \Magento\Framework\Controller\Result\Raw */ public function execute() { - $this->_view->loadLayout(); - $this->getResponse()->setBody( - $this->_view->getLayout()->createBlock( - 'Magento\GoogleShopping\Block\Adminhtml\Items\Item' - )->setIndex( - $this->getRequest()->getParam('index') - )->toHtml() - ); + /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ + $resultRaw = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); + /** @var \Magento\GoogleShopping\Block\Adminhtml\Items\Item $block */ + $block = $this->layoutFactory->create()->createBlock('Magento\GoogleShopping\Block\Adminhtml\Items\Item'); + return $resultRaw->setContents($block->setIndex($this->getRequest()->getParam('index'))->toHtml()); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Index.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Index.php index 56380c2148cfacfde955603861af9d03fa33fbb4..092ac1d0a4471fb21333cfa312cbeaf090d682cb 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Index.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Index.php @@ -35,54 +35,36 @@ class Index extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\ $this->urlDecoder = $urlDecoder; } - /** - * Initialize general settings for action - * - * @return $this - */ - protected function _initAction() - { - $this->_view->loadLayout(); - $this->_setActiveMenu( - 'Magento_GoogleShopping::catalog_googleshopping_items' - )->_addBreadcrumb( - __('Catalog'), - __('Catalog') - )->_addBreadcrumb( - __('Google Content'), - __('Google Content') - ); - return $this; - } - /** * Manage Items page with two item grids: Magento products and Google Content items * - * @return void + * @return \Magento\Backend\Model\View\Result\Page|\Magento\Backend\Model\View\Result\Redirect */ public function execute() { if (0 === (int)$this->getRequest()->getParam('store')) { - $this->_redirect( + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT); + return $resultRedirect->setPath( 'adminhtml/*/', [ - 'store' => $this->_objectManager->get( - 'Magento\Store\Model\StoreManagerInterface' - )->getStore()->getId(), + 'store' => $this->_objectManager->get('Magento\Store\Model\StoreManagerInterface') + ->getStore()->getId(), '_current' => true ] ); - return; } - $this->_initAction(); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Google Content Items')); + /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ + $resultPage = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Magento_GoogleShopping::catalog_googleshopping_items') + ->addBreadcrumb(__('Catalog'), __('Catalog')) + ->addBreadcrumb(__('Google Content'), __('Google Content')); + $resultPage->getConfig()->getTitle()->prepend(__('Google Content Items')); - $contentBlock = $this->_view->getLayout()->createBlock( - 'Magento\GoogleShopping\Block\Adminhtml\Items' - )->setStore( - $this->_getStore() - ); + $contentBlock = $resultPage->getLayout() + ->createBlock('Magento\GoogleShopping\Block\Adminhtml\Items') + ->setStore($this->_getStore()); if ($this->getRequest()->getParam('captcha_token') && $this->getRequest()->getParam('captcha_url')) { $contentBlock->setGcontentCaptchaToken( @@ -97,11 +79,8 @@ class Index extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\ ); } - if (!$this->_objectManager->get( - 'Magento\GoogleShopping\Model\Config' - )->isValidDefaultCurrencyCode( - $this->_getStore()->getId() - ) + if (!$this->_objectManager->get('Magento\GoogleShopping\Model\Config') + ->isValidDefaultCurrencyCode($this->_getStore()->getId()) ) { $_countryInfo = $this->_objectManager->get( 'Magento\GoogleShopping\Model\Config' @@ -110,14 +89,14 @@ class Index extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\ ); $this->messageManager->addNotice( __( - "The store's currency should be set to %1 for %2 in system configuration. Otherwise item prices won't be correct in Google Content.", + "The store's currency should be set to %1 for %2 in system configuration." + . " Otherwise item prices won't be correct in Google Content.", $_countryInfo['currency_name'], $_countryInfo['name'] ) ); } - $this->_addBreadcrumb(__('Items'), __('Items'))->_addContent($contentBlock); - $this->_view->renderLayout(); + return $resultPage->addBreadcrumb(__('Items'), __('Items'))->addContent($contentBlock); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php index 4af5444a043b464a7403dbf8d73e1e7cd0a93b12..4f101189769876999ba8e662e2bb2f711a653dda 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -11,13 +10,14 @@ class MassAdd extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin /** * Add (export) several products to Google Content * - * @return void + * @return \Magento\Framework\Controller\ResultInterface + * @throws \Magento\Framework\Exception\LocalizedException */ public function execute() { $flag = $this->_getFlag(); if ($flag->isLocked()) { - return; + return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); } session_write_close(); @@ -29,20 +29,14 @@ class MassAdd extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin try { $flag->lock(); - $this->_objectManager->create( - 'Magento\GoogleShopping\Model\MassOperations' - )->setFlag( - $flag - )->addProducts( - $productIds, - $storeId - ); + $this->_objectManager->create('Magento\GoogleShopping\Model\MassOperations') + ->setFlag($flag) + ->addProducts($productIds, $storeId); } catch (\Zend_Gdata_App_CaptchaRequiredException $e) { // Google requires CAPTCHA for login $this->messageManager->addError(__($e->getMessage())); $flag->unlock(); - $this->_redirectToCaptcha($e); - return; + return $this->_redirectToCaptcha($e); } catch (\Exception $e) { $flag->unlock(); $this->notifier->addMajor( @@ -50,9 +44,10 @@ class MassAdd extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin $e->getMessage() ); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); - return; + return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); } $flag->unlock(); + return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php index 03fc43a2939797febd4ccdcc5bb1b837a3e9783c..60795768337b509e918aa33877ee4f8b5df2b447 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php @@ -1,7 +1,5 @@ <?php /** - * Update items statistics and remove the items which are not available in Google Content - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -10,6 +8,9 @@ namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Items; +/** + * Update items statistics and remove the items which are not available in Google Content + */ class Refresh extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Items { /** @@ -20,13 +21,13 @@ class Refresh extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin protected $operation = 'synchronizeItems'; /** - * {@inheritdoc} + * @return \Magento\Framework\Controller\ResultInterface */ public function execute() { $flag = $this->_getFlag(); if ($flag->isLocked()) { - return; + return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); } session_write_close(); @@ -38,19 +39,14 @@ class Refresh extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin try { $flag->lock(); $operation = $this->operation; - $this->_objectManager->create( - 'Magento\GoogleShopping\Model\MassOperations' - )->setFlag( - $flag - )->$operation( - $itemIds - ); + $this->_objectManager->create('Magento\GoogleShopping\Model\MassOperations') + ->setFlag($flag) + ->$operation($itemIds); } catch (\Zend_Gdata_App_CaptchaRequiredException $e) { // Google requires CAPTCHA for login $this->messageManager->addError(__($e->getMessage())); $flag->unlock(); - $this->_redirectToCaptcha($e); - return; + return $this->_redirectToCaptcha($e); } catch (\Exception $e) { $flag->unlock(); $this->notifier->addMajor( @@ -60,9 +56,10 @@ class Refresh extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin ) ); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); - return; + return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); } $flag->unlock(); + return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Status.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Status.php index 02e72b6a7ccbd2cacba6d2570eeda4740d0b353e..373b05d547cc4c3818e3558a3242ecd21afeb422 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Status.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Status.php @@ -11,16 +11,16 @@ class Status extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping /** * Retrieve background process status * - * @return \Magento\Framework\App\Response\Http + * @return \Magento\Framework\Controller\Result\Json */ public function execute() { if ($this->getRequest()->isAjax()) { $this->getResponse()->setHeader('Content-Type', 'application/json'); $params = ['is_running' => $this->_getFlag()->isLocked()]; - return $this->getResponse()->representJson( - $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode($params) - ); + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_JSON); + return $resultJson->setData($params); } } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Grid.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Grid.php index a8c5ec7e749d33b799233a0b402fc79f4e9bc065..c3103f9882740b17732fa8946c3d134f75045c8c 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Grid.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Grid.php @@ -8,20 +8,35 @@ namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Selection; class Grid extends \Magento\Backend\App\Action { + /** + * @var \Magento\Framework\View\LayoutFactory + */ + protected $layoutFactory; + + /** + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Framework\View\LayoutFactory $layoutFactory + */ + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\View\LayoutFactory $layoutFactory + ) { + $this->layoutFactory = $layoutFactory; + parent::__construct($context); + } + /** * Grid with available products for Google Content * - * @return void + * @return \Magento\Framework\Controller\Result\Raw */ public function execute() { - $this->_view->loadLayout(); - $this->getResponse()->setBody( - $this->_view->getLayout()->createBlock( - 'Magento\GoogleShopping\Block\Adminhtml\Items\Product' - )->setIndex( - $this->getRequest()->getParam('index') - )->toHtml() + /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ + $resultRaw = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); + return $resultRaw->setContents( + $this->layoutFactory->create()->createBlock('Magento\GoogleShopping\Block\Adminhtml\Items\Product') + ->setIndex($this->getRequest()->getParam('index'))->toHtml() ); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Search.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Search.php index 487ae3016ae2994d2d142c87cb5dfcd3e7c5b648..8a86f1fd794f8b4fdf8be9127c1a23e49fdb2dab 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Search.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Selection/Search.php @@ -8,21 +8,35 @@ namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Selection; class Search extends \Magento\Backend\App\Action { + /** + * @var \Magento\Framework\View\LayoutFactory + */ + protected $layoutFactory; + + /** + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Framework\View\LayoutFactory $layoutFactory + */ + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\View\LayoutFactory $layoutFactory + ) { + $this->layoutFactory = $layoutFactory; + parent::__construct($context); + } + /** * Search result grid with available products for Google Content * - * @return void + * @return \Magento\Framework\Controller\Result\Raw */ public function execute() { - $this->getResponse()->setBody( - $this->_view->getLayout()->createBlock( - 'Magento\GoogleShopping\Block\Adminhtml\Items\Product' - )->setIndex( - $this->getRequest()->getParam('index') - )->setFirstShow( - true - )->toHtml() + /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ + $resultRaw = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); + return $resultRaw->setContents( + $this->layoutFactory->create()->createBlock('Magento\GoogleShopping\Block\Adminhtml\Items\Product') + ->setIndex($this->getRequest()->getParam('index'))->setFirstShow(true)->toHtml() ); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types.php index a233721ed9f907b4c715ecd96d7389851b3e6a17..068fa2cdf168fd1e33bb838ca4dfa0508f2724fd 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types.php @@ -68,21 +68,16 @@ class Types extends \Magento\Backend\App\Action /** * Initialize general settings for action * - * @return $this + * @return \Magento\Backend\Model\View\Result\Page */ - protected function _initAction() + protected function initPage() { - $this->_view->loadLayout(); - $this->_setActiveMenu( - 'Magento_GoogleShopping::catalog_googleshopping_types' - )->_addBreadcrumb( - __('Catalog'), - __('Catalog') - )->_addBreadcrumb( - __('Google Content'), - __('Google Content') - ); - return $this; + /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ + $resultPage = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Magento_GoogleShopping::catalog_googleshopping_types') + ->addBreadcrumb(__('Catalog'), __('Catalog')) + ->addBreadcrumb(__('Google Content'), __('Google Content')); + return $resultPage; } /** diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php index 89648aa1adabaa42ab4d07e41b667056e25e5fcc..e3f5eb02d2406786e6222f31416041c308bf5f9e 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php @@ -11,7 +11,7 @@ class Edit extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\T /** * Edit attribute set mapping * - * @return void + * @return \Magento\Backend\Model\View\Result\Page|\Magento\Backend\Model\View\Result\Redirect */ public function execute() { @@ -21,11 +21,9 @@ class Edit extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\T try { $result = []; if ($typeId) { - $collection = $this->_objectManager->create( - 'Magento\GoogleShopping\Model\Resource\Attribute\Collection' - )->addTypeFilter( - $typeId - )->load(); + $collection = $this->_objectManager + ->create('Magento\GoogleShopping\Model\Resource\Attribute\Collection') + ->addTypeFilter($typeId)->load(); foreach ($collection as $attribute) { $result[] = $attribute->getData(); } @@ -34,19 +32,22 @@ class Edit extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\T $this->_coreRegistry->register('attributes', $result); $breadcrumbLabel = $typeId ? __('Edit attribute set mapping') : __('New attribute set mapping'); - $this->_initAction()->_addBreadcrumb( - $breadcrumbLabel, - $breadcrumbLabel - )->_addContent( - $this->_view->getLayout()->createBlock('Magento\GoogleShopping\Block\Adminhtml\Types\Edit') - ); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Google Content Attribute Mapping')); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Google Content Attributes')); - $this->_view->renderLayout(); + + $resultPage = $this->initPage(); + $resultPage->addBreadcrumb($breadcrumbLabel, $breadcrumbLabel) + ->addContent( + $resultPage->getLayout()->createBlock('Magento\GoogleShopping\Block\Adminhtml\Types\Edit') + ); + + $resultPage->getConfig()->getTitle()->prepend(__('Google Content Attribute Mapping')); + $resultPage->getConfig()->getTitle()->prepend(__('Google Content Attributes')); + return $resultPage; } catch (\Exception $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->messageManager->addError(__("We can't edit Attribute Set Mapping.")); - $this->_redirect('adminhtml/*/index'); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT); + return $resultRedirect->setPath('adminhtml/*/index'); } } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Grid.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Grid.php index 1418bc0242a11271ec54d23ef3768dc6cce86141..91270934b4154ba019d2766c6c8911b1f8c64964 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Grid.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Grid.php @@ -11,11 +11,10 @@ class Grid extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\T /** * Grid for AJAX request * - * @return void + * @return \Magento\Framework\View\Result\Layout */ public function execute() { - $this->_view->loadLayout('false'); - $this->_view->renderLayout(); + return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_LAYOUT); } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Index.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Index.php index 30232cbe3d40df6ca6d84739e4d94ba98ce1720d..b6116c7316a0283956bf4f8a049e2509c2f691a6 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Index.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Index.php @@ -11,12 +11,12 @@ class Index extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\ /** * List of all maps (items) * - * @return void + * @return \Magento\Backend\Model\View\Result\Page */ public function execute() { - $this->_initAction()->_addBreadcrumb(__('Attribute Maps'), __('Attribute Maps')); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Google Content Attributes')); - $this->_view->renderLayout(); + $resultPage = $this->initPage()->addBreadcrumb(__('Attribute Maps'), __('Attribute Maps')); + $resultPage->getConfig()->getTitle()->prepend(__('Google Content Attributes')); + return $resultPage; } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php index 6cb5d6885d1355e0049abc808c63bc297ea878c4..fc8a1dc2bd6ccf7ed9b86858edf1983d0308de52 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,16 +7,37 @@ namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Types; class LoadAttributeSets extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Types { + /** + * @var \Magento\Framework\View\LayoutFactory + */ + protected $layoutFactory; + + /** + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Framework\Registry $coreRegistry + * @param \Magento\Framework\View\LayoutFactory $layoutFactory + */ + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\Registry $coreRegistry, + \Magento\Framework\View\LayoutFactory $layoutFactory + ) { + $this->layoutFactory = $layoutFactory; + parent::__construct($context, $coreRegistry); + } + /** * Get available attribute sets * - * @return void + * @return \Magento\Framework\Controller\Result\Raw * @throws \Exception */ public function execute() { - $this->getResponse()->setBody( - $this->_view->getLayout()->getBlockSingleton('Magento\GoogleShopping\Block\Adminhtml\Types\Edit\Form') + /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ + $resultRaw = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); + return $resultRaw->setContents( + $this->layoutFactory->create()->getBlockSingleton('Magento\GoogleShopping\Block\Adminhtml\Types\Edit\Form') ->getAttributeSetsSelectElement($this->getRequest()->getParam('target_country')) ->toHtml() ); diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php index 54a0bce4af48ce45f7c35ced453aff950f94a9f3..0d817329dd869c3b8563c784190729ce2a04a394 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php @@ -8,29 +8,48 @@ namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Types; class LoadAttributes extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Types { + /** + * @var \Magento\Framework\View\LayoutFactory + */ + protected $layoutFactory; + + /** + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Framework\Registry $coreRegistry + * @param \Magento\Framework\View\LayoutFactory $layoutFactory + */ + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\Registry $coreRegistry, + \Magento\Framework\View\LayoutFactory $layoutFactory + ) { + $this->layoutFactory = $layoutFactory; + parent::__construct($context, $coreRegistry); + } + /** * Get Google Content attributes list * - * @return void + * @return \Magento\Framework\Controller\Result\Raw */ public function execute() { + /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ + $resultRaw = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); try { - $this->getResponse()->setBody( - $this->_view->getLayout()->createBlock( - 'Magento\GoogleShopping\Block\Adminhtml\Types\Edit\Attributes' - )->setAttributeSetId( - $this->getRequest()->getParam('attribute_set_id') - )->setTargetCountry( - $this->getRequest()->getParam('target_country') - )->setAttributeSetSelected( - true - )->toHtml() + $resultRaw->setContents( + $this->layoutFactory->create() + ->createBlock('Magento\GoogleShopping\Block\Adminhtml\Types\Edit\Attributes') + ->setAttributeSetId($this->getRequest()->getParam('attribute_set_id')) + ->setTargetCountry($this->getRequest()->getParam('target_country')) + ->setAttributeSetSelected(true) + ->toHtml() ); } catch (\Exception $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); // just need to output text with error $this->messageManager->addError(__("We can't load attributes.")); } + return $resultRaw; } } diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php index ffb8ee171b7f6fc7c7466178b5b67e04f7e481a3..86b62a33b9c033d19c3153b56161a5e769cacb1c 100644 --- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php +++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -11,25 +10,31 @@ class NewAction extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopp /** * Create new attribute set mapping * - * @return void + * @return \Magento\Backend\Model\View\Result\Page|\Magento\Backend\Model\View\Result\Redirect */ public function execute() { try { $this->_initItemType(); - $this->_initAction()->_addBreadcrumb( + + /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ + $resultPage = $this->initPage()->addBreadcrumb( __('New attribute set mapping'), __('New attribute set mapping') - )->_addContent( - $this->_view->getLayout()->createBlock('Magento\GoogleShopping\Block\Adminhtml\Types\Edit') ); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Google Content Attributes')); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('New Google Content Attribute Mapping')); - $this->_view->renderLayout(); + $resultPage->addContent( + $resultPage->getLayout()->createBlock('Magento\GoogleShopping\Block\Adminhtml\Types\Edit') + ); + $resultPage->getConfig()->getTitle()->prepend(__('Google Content Attributes')); + $resultPage->getConfig()->getTitle()->prepend(__('New Google Content Attribute Mapping')); + return $resultPage; } catch (\Exception $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->messageManager->addError(__("We can't create Attribute Set Mapping.")); - $this->_redirect('adminhtml/*/index', ['store' => $this->_getStore()->getId()]); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT); + $resultRedirect->setPath('adminhtml/*/index', ['store' => $this->_getStore()->getId()]); + return $resultRedirect; } } } diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php b/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php index 089f14216bdadb05a1ee8c4b4530526b46ad892a..d20e9cc0cc88c9215df5aa15b0b69cd32ccb5061 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php @@ -8,6 +8,7 @@ namespace Magento\GoogleShopping\Model\Attribute; use Magento\Framework\Parse\Zip; use Magento\Store\Model\Store; use Magento\Tax\Api\Data\TaxClassKeyInterface; +use Magento\Tax\Model\TaxClass\Key; /** * Tax attribute model @@ -179,8 +180,8 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute 'code' => $product->getSku(), 'type' => 'product', 'tax_class_key' => [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, - TaxClassKeyInterface::KEY_VALUE => $product->getTaxClassId(), + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, + Key::KEY_VALUE => $product->getTaxClassId(), ], 'unit_price' => $product->getPrice(), 'quantity' => 1, @@ -204,8 +205,8 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute 'billing_address' => $billingAddressDataArray, 'shipping_address' => $shippingAddressDataArray, 'customer_tax_class_key' => [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, - TaxClassKeyInterface::KEY_VALUE => $defaultCustomerTaxClassId, + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, + Key::KEY_VALUE => $defaultCustomerTaxClassId, ], 'items' => [ $quoteDetailsItemDataArray, diff --git a/app/code/Magento/GoogleShopping/composer.json b/app/code/Magento/GoogleShopping/composer.json index 267a3c8cb23aeea71338a8532432c3e4a133ce26..6960954e41d5609fece948947ce2eb7bf0f89ed2 100644 --- a/app/code/Magento/GoogleShopping/composer.json +++ b/app/code/Magento/GoogleShopping/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GroupedImportExport/composer.json b/app/code/Magento/GroupedImportExport/composer.json index 2d66faa4f5b3761512df683740754d918999fe0c..b74fc2be667c10aebcb7067d20923281e1c17cf0 100644 --- a/app/code/Magento/GroupedImportExport/composer.json +++ b/app/code/Magento/GroupedImportExport/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-import-export": "0.74.0-beta6", - "magento/module-catalog-import-export": "0.74.0-beta6", - "magento/module-grouped-product": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-import-export": "0.74.0-beta7", + "magento/module-catalog-import-export": "0.74.0-beta7", + "magento/module-grouped-product": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index d856527779116c8c6795c79d704fc90a892bfcd2..5ee51f1ecbfb45622fd6f8c28955de99da4c2874 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -480,7 +480,7 @@ class Grouped extends \Magento\Catalog\Model\Product\Type\AbstractType */ public function beforeSave($product) { - if ($product->hasData('product_options')) { + if ($product->hasData('product_options') && !empty($product->getData('product_options'))) { throw new \Exception('Custom options for grouped product type are not supported'); } return parent::beforeSave($product); diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Model/ProductTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Model/ProductTest.php new file mode 100644 index 0000000000000000000000000000000000000000..04d7f729f8c86ad5a0c85435bfa266584cf3fbb1 --- /dev/null +++ b/app/code/Magento/GroupedProduct/Test/Unit/Model/ProductTest.php @@ -0,0 +1,430 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\GroupedProduct\Test\Unit\Model; + +use \Magento\Catalog\Model\Product; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Product Test + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) + * + */ +class ProductTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManagerHelper + */ + protected $objectManagerHelper; + + /** + * @var \Magento\Catalog\Model\Product + */ + protected $model; + + /** + * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject + */ + protected $moduleManager; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $stockItemFactoryMock; + + /** + * @var \Magento\Indexer\Model\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $categoryIndexerMock; + + /** + * @var \Magento\Catalog\Model\Indexer\Product\Flat\Processor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productFlatProcessor; + + /** + * @var \Magento\Catalog\Model\Indexer\Product\Price\Processor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productPriceProcessor; + + /** + * @var Product\Type|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productTypeInstanceMock; + + /** + * @var Product\Option|\PHPUnit_Framework_MockObject_MockObject + */ + protected $optionInstanceMock; + + /** + * @var \Magento\Framework\Pricing\PriceInfo\Base|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_priceInfoMock; + + /** + * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var \Magento\Catalog\Model\Resource\Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $resource; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + private $registry; + + /** + * @var \Magento\Catalog\Model\Category|\PHPUnit_Framework_MockObject_MockObject + */ + private $category; + + /** + * @var \Magento\Store\Model\Website|\PHPUnit_Framework_MockObject_MockObject + */ + private $website; + + /** + * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $indexerRegistryMock; + + /** + * @var \Magento\Catalog\Api\CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryRepository; + + /** + * @var \Magento\Catalog\Helper\Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $_catalogProduct; + + /** + * @var \Magento\Catalog\Model\Product\Image\Cache|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageCache; + + /** + * @var \Magento\Catalog\Model\Product\Image\CacheFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageCacheFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $mediaGalleryEntryFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productLinkFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $dataObjectHelperMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $metadataServiceMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $attributeValueFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $linkTypeProviderMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $entityCollectionProviderMock; + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function setUp() + { + $this->categoryIndexerMock = $this->getMockForAbstractClass('\Magento\Indexer\Model\IndexerInterface'); + + $this->moduleManager = $this->getMock( + 'Magento\Framework\Module\Manager', + ['isEnabled'], + [], + '', + false + ); + $this->stockItemFactoryMock = $this->getMock( + 'Magento\CatalogInventory\Api\Data\StockItemInterfaceFactory', + ['create'], + [], + '', + false + ); + $this->dataObjectHelperMock = $this->getMockBuilder('\Magento\Framework\Api\DataObjectHelper') + ->disableOriginalConstructor() + ->getMock(); + $this->productFlatProcessor = $this->getMock( + 'Magento\Catalog\Model\Indexer\Product\Flat\Processor', + [], + [], + '', + false + ); + + $this->_priceInfoMock = $this->getMock('Magento\Framework\Pricing\PriceInfo\Base', [], [], '', false); + $this->productTypeInstanceMock = $this->getMock('Magento\Catalog\Model\Product\Type', [], [], '', false); + $this->productPriceProcessor = $this->getMock( + 'Magento\Catalog\Model\Indexer\Product\Price\Processor', + [], + [], + '', + false + ); + + $stateMock = $this->getMock('Magento\FrameworkApp\State', ['getAreaCode'], [], '', false); + $stateMock->expects($this->any()) + ->method('getAreaCode') + ->will($this->returnValue(\Magento\Backend\App\Area\FrontNameResolver::AREA_CODE)); + + $eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface'); + $actionValidatorMock = $this->getMock( + '\Magento\Framework\Model\ActionValidator\RemoveAction', + [], + [], + '', + false + ); + $actionValidatorMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true)); + $cacheInterfaceMock = $this->getMock('Magento\Framework\App\CacheInterface'); + + $contextMock = $this->getMock( + '\Magento\Framework\Model\Context', + ['getEventDispatcher', 'getCacheManager', 'getAppState', 'getActionValidator'], [], '', false + ); + $contextMock->expects($this->any())->method('getAppState')->will($this->returnValue($stateMock)); + $contextMock->expects($this->any())->method('getEventDispatcher')->will($this->returnValue($eventManagerMock)); + $contextMock->expects($this->any()) + ->method('getCacheManager') + ->will($this->returnValue($cacheInterfaceMock)); + $contextMock->expects($this->any()) + ->method('getActionValidator') + ->will($this->returnValue($actionValidatorMock)); + + $this->optionInstanceMock = $this->getMockBuilder('Magento\Catalog\Model\Product\Option') + ->setMethods(['setProduct', 'saveOptions', '__wakeup', '__sleep']) + ->disableOriginalConstructor()->getMock(); + + $this->resource = $this->getMockBuilder('Magento\Catalog\Model\Resource\Product') + ->disableOriginalConstructor() + ->getMock(); + + $this->registry = $this->getMockBuilder('Magento\Framework\Registry') + ->disableOriginalConstructor() + ->getMock(); + + $this->category = $this->getMockBuilder('Magento\Catalog\Model\Category') + ->disableOriginalConstructor() + ->getMock(); + + $this->store = $this->getMockBuilder('Magento\Store\Model\Store') + ->disableOriginalConstructor() + ->getMock(); + + $this->website = $this->getMockBuilder('\Magento\Store\Model\Website') + ->disableOriginalConstructor() + ->getMock(); + + $storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $storeManager->expects($this->any()) + ->method('getStore') + ->will($this->returnValue($this->store)); + $storeManager->expects($this->any()) + ->method('getWebsite') + ->will($this->returnValue($this->website)); + $this->indexerRegistryMock = $this->getMock('Magento\Indexer\Model\IndexerRegistry', ['get'], [], '', false); + $this->categoryRepository = $this->getMock('Magento\Catalog\Api\CategoryRepositoryInterface'); + + $this->_catalogProduct = $this->getMock( + 'Magento\Catalog\Helper\Product', + ['isDataForProductCategoryIndexerWasChanged'], + [], + '', + false + ); + + $this->imageCache = $this->getMockBuilder('Magento\Catalog\Model\Product\Image\Cache') + ->disableOriginalConstructor() + ->getMock(); + $this->imageCacheFactory = $this->getMockBuilder('Magento\Catalog\Model\Product\Image\CacheFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->productLinkFactory = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductLinkInterfaceFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->mediaGalleryEntryFactoryMock = + $this->getMockBuilder('Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterfaceFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->metadataServiceMock = $this->getMock('\Magento\Catalog\Api\ProductAttributeRepositoryInterface'); + $this->attributeValueFactory = $this->getMockBuilder('Magento\Framework\Api\AttributeValueFactory') + ->disableOriginalConstructor()->getMock(); + $this->linkTypeProviderMock = $this->getMock('Magento\Catalog\Model\Product\LinkTypeProvider', + ['getLinkTypes'], [], '', false); + $this->entityCollectionProviderMock = $this->getMock('Magento\Catalog\Model\ProductLink\CollectionProvider', + ['getCollection'], [], '', false); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $this->objectManagerHelper->getObject( + 'Magento\Catalog\Model\Product', + [ + 'context' => $contextMock, + 'catalogProductType' => $this->productTypeInstanceMock, + 'productFlatIndexerProcessor' => $this->productFlatProcessor, + 'productPriceIndexerProcessor' => $this->productPriceProcessor, + 'catalogProductOption' => $this->optionInstanceMock, + 'storeManager' => $storeManager, + 'resource' => $this->resource, + 'registry' => $this->registry, + 'moduleManager' => $this->moduleManager, + 'stockItemFactory' => $this->stockItemFactoryMock, + 'dataObjectHelper' => $this->dataObjectHelperMock, + 'indexerRegistry' => $this->indexerRegistryMock, + 'categoryRepository' => $this->categoryRepository, + 'catalogProduct' => $this->_catalogProduct, + 'imageCacheFactory' => $this->imageCacheFactory, + 'productLinkFactory' => $this->productLinkFactory, + 'mediaGalleryEntryFactory' => $this->mediaGalleryEntryFactoryMock, + 'metadataService' => $this->metadataServiceMock, + 'customAttributeFactory' => $this->attributeValueFactory, + 'entityCollectionProvider' => $this->entityCollectionProviderMock, + 'linkTypeProvider' => $this->linkTypeProviderMock, + 'data' => ['id' => 1] + ] + ); + + } + + /** + * Test for getProductLinks() with associated product links + */ + public function testGetProductLinks() + { + $this->markTestIncomplete('Skipped due to https://jira.corp.x.com/browse/MAGETWO-36926'); + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $inputRelatedLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku("Simple Product 1"); + $inputRelatedLink->setLinkType("related"); + $inputRelatedLink->setData("sku", "Simple Product 2"); + $inputRelatedLink->setData("type", "simple"); + $inputRelatedLink->setPosition(0); + + $customData = ["attribute_code" => "qty", "value" => 1]; + $inputGroupLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputGroupLink->setProductSku("Simple Product 1"); + $inputGroupLink->setLinkType("associated"); + $inputGroupLink->setData("sku", "Simple Product 2"); + $inputGroupLink->setData("type", "simple"); + $inputGroupLink->setPosition(0); + $inputGroupLink["custom_attributes"] = [$customData]; + + $outputRelatedLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $outputRelatedLink->setProductSku("Simple Product 1"); + $outputRelatedLink->setLinkType("related"); + $outputRelatedLink->setLinkedProductSku("Simple Product 2"); + $outputRelatedLink->setLinkedProductType("simple"); + $outputRelatedLink->setPosition(0); + + $groupExtension = $this->objectManagerHelper->getObject('Magento\Catalog\Api\Data\ProductLinkExtension'); + $reflectionOfExtension = new \ReflectionClass('Magento\Catalog\Api\Data\ProductLinkExtension'); + $method = $reflectionOfExtension->getMethod('setData'); + $method->setAccessible(true); + $method->invokeArgs($groupExtension, array('qty', 1)); + + $outputGroupLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $outputGroupLink->setProductSku("Simple Product 1"); + $outputGroupLink->setLinkType("associated"); + $outputGroupLink->setLinkedProductSku("Simple Product 2"); + $outputGroupLink->setLinkedProductType("simple"); + $outputGroupLink->setPosition(0); + $outputGroupLink->setExtensionAttributes($groupExtension); + + $this->entityCollectionProviderMock->expects($this->at(0)) + ->method('getCollection') + ->with($this->model, 'related') + ->willReturn([$inputRelatedLink]); + $this->entityCollectionProviderMock->expects($this->at(1)) + ->method('getCollection') + ->with($this->model, 'upsell') + ->willReturn([]); + $this->entityCollectionProviderMock->expects($this->at(2)) + ->method('getCollection') + ->with($this->model, 'crosssell') + ->willReturn([]); + $this->entityCollectionProviderMock->expects($this->at(3)) + ->method('getCollection') + ->with($this->model, 'associated') + ->willReturn([$inputGroupLink]); + + $expectedOutput = [$outputRelatedLink, $outputGroupLink]; + $typeInstanceMock = $this->getMock( + 'Magento\ConfigurableProduct\Model\Product\Type\Simple', ["getSku"], [], '', false); + $typeInstanceMock + ->expects($this->atLeastOnce()) + ->method('getSku') + ->willReturn("Simple Product 1"); + $this->model->setTypeInstance($typeInstanceMock); + + $productLink1 = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $productLink2 = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); + $this->productLinkFactory->expects($this->at(0)) + ->method('create') + ->willReturn($productLink1); + $this->productLinkFactory->expects($this->at(1)) + ->method('create') + ->willReturn($productLink2); + + $extension = $this->objectManagerHelper->getObject('Magento\Catalog\Api\Data\ProductLinkExtension'); + $productLink2->setExtensionAttributes($extension); + + $links = $this->model->getProductLinks(); + // Match the links + $matches = 0; + foreach ($links as $link) { + foreach ($expectedOutput as $expected) { + if ($expected->getData() == $link->getData()) { + $matches++; + } + } + } + $this->assertEquals($matches, 2); + } +} diff --git a/app/code/Magento/GroupedProduct/composer.json b/app/code/Magento/GroupedProduct/composer.json index cdd8818ca6b36d0d881e58e187ae078e61590d0c..69f557ba1be410195e5790a509f47302711c3173 100644 --- a/app/code/Magento/GroupedProduct/composer.json +++ b/app/code/Magento/GroupedProduct/composer.json @@ -3,22 +3,22 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/module-msrp": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/module-msrp": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GroupedProduct/etc/data_object.xml b/app/code/Magento/GroupedProduct/etc/service_data_attributes.xml similarity index 66% rename from app/code/Magento/GroupedProduct/etc/data_object.xml rename to app/code/Magento/GroupedProduct/etc/service_data_attributes.xml index d6a76ebaa081f2e742c78e66d70dc504c460bdde..0618cc9286cfd8ccb0cab46f6a505b05a39c4ee2 100644 --- a/app/code/Magento/GroupedProduct/etc/data_object.xml +++ b/app/code/Magento/GroupedProduct/etc/service_data_attributes.xml @@ -5,8 +5,8 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Catalog\Api\Data\ProductLinkInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Catalog\Api\Data\ProductLinkInterface"> <attribute code="qty" type="float" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/templates/catalog/product/composite/fieldset/grouped.phtml b/app/code/Magento/GroupedProduct/view/adminhtml/templates/catalog/product/composite/fieldset/grouped.phtml index 0a09bcdf7488f7cc713a1a13a9f8b05e1027262d..08f14bf4c075522f0ef228743d89de74221b1b21 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/templates/catalog/product/composite/fieldset/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/templates/catalog/product/composite/fieldset/grouped.phtml @@ -20,7 +20,7 @@ <?php if ((!$_product->isAvailable() && !$_skipSaleableCheck) || !$_hasAssociatedProducts): ?> <p class="availability out-of-stock"><?php echo __('Availability:') ?> <span><?php echo __('Out of stock') ?></span></p> <?php endif; ?> - <table class="data-table table-info grouped-items-table" id="super-product-table"> + <table class="data-table admin__table-primary grouped-items-table" id="super-product-table"> <thead> <tr class="headings"> <th class="col-id"><?php echo __('ID') ?></th> diff --git a/app/code/Magento/ImportExport/composer.json b/app/code/Magento/ImportExport/composer.json index 747df1717017a7ddeffb4d80ef8640f23e2f5dfd..cc859dbe4b4f79012ea771cf2434247ea9b8cd5c 100644 --- a/app/code/Magento/ImportExport/composer.json +++ b/app/code/Magento/ImportExport/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-indexer": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-indexer": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "ext-ctype": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml index 98557c0254c317fbcb7b6803508e9759e222e90b..26275ec71c97b8efd83193db658f05ac0632d576 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/after.phtml @@ -9,7 +9,7 @@ <span class="icon-head head-edit-form fieldset-legend" id="import_validation_container_header"><?php echo __('Validation Results'); ?></span> </div><br> - <div id="import_validation_messages" class="fieldset admin__scope"><!-- --></div> + <div id="import_validation_messages" class="fieldset"><!-- --></div> </div> <script> require(['jquery', 'prototype'], function(jQuery){ diff --git a/app/code/Magento/Indexer/composer.json b/app/code/Magento/Indexer/composer.json index 13b2594e6abd971cfa42adbb147d542bb9f30c3a..b346637038367b28a5ad2c08d5d57e1bed717eaa 100644 --- a/app/code/Magento/Indexer/composer.json +++ b/app/code/Magento/Indexer/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-page-cache": "0.74.0-beta6", - "magento/framework": "0.74.0-beta4", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-page-cache": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Integration/composer.json b/app/code/Magento/Integration/composer.json index 9fa6582f0d0cd4bb38e11ceed92222616d1abd5a..0c5cf5c42e60e1228d5701fe8df076f5f3c64547 100644 --- a/app/code/Magento/Integration/composer.json +++ b/app/code/Magento/Integration/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-user": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-authorization": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-user": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-authorization": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/LayeredNavigation/composer.json b/app/code/Magento/LayeredNavigation/composer.json index ed19740fa51a2ec85a258179adb1147d47cbe49e..3651e00bcad830257b36b43b9ca6ff3da9ca0fe4 100644 --- a/app/code/Magento/LayeredNavigation/composer.json +++ b/app/code/Magento/LayeredNavigation/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Log/composer.json b/app/code/Magento/Log/composer.json index 5179484e4165391b9d64e747c7cde887bacdc2c5..3673638d5fdf881571d1fc6d10276dd7c134415d 100644 --- a/app/code/Magento/Log/composer.json +++ b/app/code/Magento/Log/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/MediaStorage/composer.json b/app/code/Magento/MediaStorage/composer.json index 1a140593019d9982ad679be6ab959f95baf4ac63..e2ff84226413e9021790faeec53aa2c04734bc46 100644 --- a/app/code/Magento/MediaStorage/composer.json +++ b/app/code/Magento/MediaStorage/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Msrp/composer.json b/app/code/Magento/Msrp/composer.json index 5e288eaebe15fdb2d3d2c35d2fa2ca7de5fd5dae..3ddcf10eef3fd3ae49d4bd7ab71c2f74fe5da3df 100644 --- a/app/code/Magento/Msrp/composer.json +++ b/app/code/Magento/Msrp/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-bundle": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-downloadable": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-grouped-product": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-bundle": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-downloadable": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-grouped-product": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Multishipping/composer.json b/app/code/Magento/Multishipping/composer.json index ebcccdf5ade42bf663bb71b3bf0c100e6800df47..8b782fc5aa17d9f3702bf2e6babe60e105e3eccf 100644 --- a/app/code/Magento/Multishipping/composer.json +++ b/app/code/Magento/Multishipping/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-payment": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-payment": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Newsletter/Model/Session.php b/app/code/Magento/Newsletter/Model/Session.php index 18d680df142601fb39eab95181cee59a79cca4cb..2ffb0b2f25236066922a7510267f10135c1a518f 100644 --- a/app/code/Magento/Newsletter/Model/Session.php +++ b/app/code/Magento/Newsletter/Model/Session.php @@ -8,7 +8,7 @@ namespace Magento\Newsletter\Model; /** * Newsletter session model */ -class Session extends \Magento\Framework\Session\Generic +class Session extends \Magento\Framework\Session\SessionManager { /** * Set error message diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php index f2885610281947d30f55abdccb526e6a270c6ac4..5fa2c3aa052638f3841cefcc5ddfe6bf1ef4358a 100644 --- a/app/code/Magento/Newsletter/Model/Subscriber.php +++ b/app/code/Magento/Newsletter/Model/Subscriber.php @@ -442,7 +442,6 @@ class Subscriber extends \Magento\Framework\Model\AbstractModel $this->setStatusChanged(true); try { - $this->save(); if ($isConfirmNeed === true && $isOwnSubscribes === false ) { @@ -450,6 +449,7 @@ class Subscriber extends \Magento\Framework\Model\AbstractModel } else { $this->sendConfirmationSuccessEmail(); } + $this->save(); return $this->getStatus(); } catch (\Exception $e) { throw new \Exception($e->getMessage()); diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bd8380299a52ee06f8d95a9ddea229ae2649160e --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php @@ -0,0 +1,164 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Newsletter\Test\Unit\Model; + +class SubscriberTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Newsletter\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $newsletterData; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $scopeConfig; + + /** + * @var \Magento\Framework\Mail\Template\TransportBuilder|\PHPUnit_Framework_MockObject_MockObject + */ + protected $transportBuilder; + + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManager; + + /** + * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerSession; + + /** + * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerRepository; + + /** + * @var \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerAccountManagement; + + /** + * @var \Magento\Framework\Translate\Inline\StateInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $inlineTranslation; + + /** + * @var \Magento\Newsletter\Model\Resource\Subscriber|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resource; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + + /** + * @var \Magento\Newsletter\Model\Subscriber + */ + protected $subscriber; + + public function setUp() + { + $this->newsletterData = $this->getMock('Magento\Newsletter\Helper\Data', [], [], '', false); + $this->scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); + $this->transportBuilder = $this->getMock( + 'Magento\Framework\Mail\Template\TransportBuilder', + [ + 'setTemplateIdentifier', + 'setTemplateOptions', + 'setTemplateVars', + 'setFrom', + 'addTo', + 'getTransport' + ], + [], + '', + false + ); + $this->storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->customerSession = $this->getMock( + 'Magento\Customer\Model\Session', + [ + 'isLoggedIn', + 'getCustomerDataObject', + 'getCustomerId' + ], + [], + '', + false + ); + $this->customerRepository = $this->getMock('Magento\Customer\Api\CustomerRepositoryInterface'); + $this->customerAccountManagement = $this->getMock('Magento\Customer\Api\AccountManagementInterface'); + $this->inlineTranslation = $this->getMock('Magento\Framework\Translate\Inline\StateInterface'); + $this->resource = $this->getMock( + 'Magento\Newsletter\Model\Resource\Subscriber', + [ + 'loadByEmail', + 'getIdFieldName', + 'save' + ], + [], + '', + false + ); + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->subscriber = $this->objectManager->getObject( + 'Magento\Newsletter\Model\Subscriber', + [ + 'newsletterData' => $this->newsletterData, + 'scopeConfig' => $this->scopeConfig, + 'transportBuilder' => $this->transportBuilder, + 'storeManager' => $this->storeManager, + 'customerSession' => $this->customerSession, + 'customerRepository' => $this->customerRepository, + 'customerAccountManagement' => $this->customerAccountManagement, + 'inlineTranslation' => $this->inlineTranslation, + 'resource' => $this->resource + ] + ); + } + + public function testSubscribe() + { + $email = 'subscriber_email@magento.com'; + $this->resource->expects($this->any())->method('loadByEmail')->willReturn( + [ + 'subscriber_status' => 3, + 'subscriber_email' => $email, + 'name' => 'subscriber_name' + ] + ); + $this->resource->expects($this->any())->method('getIdFieldName')->willReturn('id_field'); + $this->scopeConfig->expects($this->any())->method('getValue')->willReturn(true); + $this->customerSession->expects($this->any())->method('isLoggedIn')->willReturn(true); + $customerDataModel = $this->getMock('\Magento\Customer\Api\Data\CustomerInterface'); + $this->customerSession->expects($this->any())->method('getCustomerDataObject')->willReturn($customerDataModel); + $this->customerSession->expects($this->any())->method('getCustomerId')->willReturn(1); + $customerDataModel->expects($this->any())->method('getEmail')->willReturn($email); + $this->customerRepository->expects($this->any())->method('getById')->willReturn($customerDataModel); + $customerDataModel->expects($this->any())->method('getStoreId')->willReturn(1); + $customerDataModel->expects($this->any())->method('getId')->willReturn(1); + $this->transportBuilder->expects($this->any())->method('setTemplateIdentifier')->willReturnSelf(); + $this->transportBuilder->expects($this->any())->method('setTemplateOptions')->willReturnSelf(); + $this->transportBuilder->expects($this->any())->method('setTemplateVars')->willReturnSelf(); + $this->transportBuilder->expects($this->any())->method('setFrom')->willReturnSelf(); + $this->transportBuilder->expects($this->any())->method('addTo')->willReturnSelf(); + $storeModel = $this->getMock('\Magento\Store\Model\Store', ['getId'], [], '', false); + $this->scopeConfig->expects($this->any())->method('getValue')->willReturn('owner_email@magento.com'); + $this->storeManager->expects($this->any())->method('getStore')->willReturn($storeModel); + $storeModel->expects($this->any())->method('getId')->willReturn(1); + $transport = $this->getMock('\Magento\Framework\Mail\TransportInterface'); + $this->transportBuilder->expects($this->any())->method('getTransport')->willReturn($transport); + $transport->expects($this->any())->method('sendMessage')->willReturnSelf(); + $inlineTranslation = $this->getMock('Magento\Framework\Translate\Inline\StateInterface'); + $inlineTranslation->expects($this->any())->method('resume')->willReturnSelf(); + $this->resource->expects($this->atLeastOnce())->method('save')->willReturnSelf(); + $this->assertEquals(1, $this->subscriber->subscribe($email)); + } +} diff --git a/app/code/Magento/Newsletter/composer.json b/app/code/Magento/Newsletter/composer.json index 2393d31c94a9e4d4840e0276b8d84bff76ea6237..27860c523bb2d47c78a20cf2e5efbb39ea2d53bc 100644 --- a/app/code/Magento/Newsletter/composer.json +++ b/app/code/Magento/Newsletter/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-email": "0.74.0-beta6", - "magento/module-cron": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-require-js": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-email": "0.74.0-beta7", + "magento/module-cron": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-require-js": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Newsletter/view/adminhtml/layout/customer_form.xml b/app/code/Magento/Newsletter/view/adminhtml/layout/customer_index_edit.xml similarity index 91% rename from app/code/Magento/Newsletter/view/adminhtml/layout/customer_form.xml rename to app/code/Magento/Newsletter/view/adminhtml/layout/customer_index_edit.xml index 047806721e82afb9d33be6cddf5f72f1da39f182..9370c60513dc798de81b4d8a88a5b3c3b5678c1b 100644 --- a/app/code/Magento/Newsletter/view/adminhtml/layout/customer_form.xml +++ b/app/code/Magento/Newsletter/view/adminhtml/layout/customer_index_edit.xml @@ -7,7 +7,7 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> - <referenceBlock name="form"> + <referenceBlock name="customer_form"> <block acl="Magento_Newsletter::subscriber" class="Magento\Customer\Block\Adminhtml\Edit\Tab\Newsletter" name="newsletter" /> </referenceBlock> </body> diff --git a/app/code/Magento/OfflinePayments/composer.json b/app/code/Magento/OfflinePayments/composer.json index f47d2c7fd2030470d1926ef74a8e7376cf9a4b78..9ec612490167fd5b8f88d2260ab37b367cdf8d73 100644 --- a/app/code/Magento/OfflinePayments/composer.json +++ b/app/code/Magento/OfflinePayments/composer.json @@ -3,12 +3,12 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-payment": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-payment": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/OfflineShipping/composer.json b/app/code/Magento/OfflineShipping/composer.json index b3ddea4da64c2a823e492e92649ee945bc126687..f78263edcb905f19c2530398ae58884d75166fd7 100644 --- a/app/code/Magento/OfflineShipping/composer.json +++ b/app/code/Magento/OfflineShipping/composer.json @@ -3,21 +3,21 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-sales-rule": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-sales-rule": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/PageCache/composer.json b/app/code/Magento/PageCache/composer.json index b8ad947ba68430c71160dc994e099cc10c073d59..c5101231ec2c5549706f8f3a139191e9153df9c0 100644 --- a/app/code/Magento/PageCache/composer.json +++ b/app/code/Magento/PageCache/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Payment/Block/Adminhtml/Transparent/Form.php b/app/code/Magento/Payment/Block/Adminhtml/Transparent/Form.php new file mode 100644 index 0000000000000000000000000000000000000000..60717bda74798f92b9f1318da44139a16df86039 --- /dev/null +++ b/app/code/Magento/Payment/Block/Adminhtml/Transparent/Form.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Block\Adminhtml\Transparent; + +class Form extends \Magento\Payment\Block\Transparent\Form +{ + /** + * On backend this block does not have any conditional checks + * + * @return bool + */ + protected function shouldRender() + { + return true; + } + + /** + * {inheritdoc} + */ + protected function initializeMethod() + { + return; + } +} diff --git a/app/code/Magento/Payment/Block/Form.php b/app/code/Magento/Payment/Block/Form.php index 762baad7f3741b485b73ac458eeed8a66434770d..f56d9ac3df0474b2d1f28bbbb16c35ea45510bc3 100644 --- a/app/code/Magento/Payment/Block/Form.php +++ b/app/code/Magento/Payment/Block/Form.php @@ -5,6 +5,8 @@ */ namespace Magento\Payment\Block; +use Magento\Payment\Model\MethodInterface; + /** * Payment method form base block */ @@ -13,14 +15,14 @@ class Form extends \Magento\Framework\View\Element\Template /** * Retrieve payment method model * - * @return \Magento\Payment\Model\MethodInterface + * @return MethodInterface * @throws \Magento\Framework\Exception\LocalizedException */ public function getMethod() { $method = $this->getData('method'); - if (!$method instanceof \Magento\Payment\Model\MethodInterface) { + if (!$method instanceof MethodInterface) { throw new \Magento\Framework\Exception\LocalizedException( __('We cannot retrieve the payment method model object.') ); @@ -28,6 +30,18 @@ class Form extends \Magento\Framework\View\Element\Template return $method; } + /** + * Sets payment method instance to form + * + * @param MethodInterface $method + * @return $this + */ + public function setMethod(MethodInterface $method) + { + $this->setData('method', $method); + return $this; + } + /** * Retrieve payment method code * diff --git a/app/code/Magento/Payment/Block/Transparent/Form.php b/app/code/Magento/Payment/Block/Transparent/Form.php new file mode 100644 index 0000000000000000000000000000000000000000..3237e6e21191af8c37ce16ff0085007d5b8d190a --- /dev/null +++ b/app/code/Magento/Payment/Block/Transparent/Form.php @@ -0,0 +1,191 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Block\Transparent; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Payment\Model\Method\TransparentInterface; +use Magento\Checkout\Model\Session; +use Magento\Payment\Model\Config; +use Magento\Framework\View\Element\Template\Context; + +/** + * Transparent form block + * + * @author Magento Core Team <core@magentocommerce.com> + */ +class Form extends \Magento\Payment\Block\Form\Cc +{ + /** + * @var Session + */ + private $checkoutSession; + + /** + * @var string + */ + protected $_template = 'Magento_Payment::transparent/form.phtml'; + + /** + * @param Context $context + * @param Config $paymentConfig + * @param Session $checkoutSession + * @param array $data + */ + public function __construct( + Context $context, + Config $paymentConfig, + Session $checkoutSession, + array $data = [] + ) { + parent::__construct($context, $paymentConfig, $data); + $this->checkoutSession = $checkoutSession; + } + + /** + * {inheritdoc} + */ + protected function _toHtml() + { + if ($this->shouldRender()) { + return $this->processHtml(); + } + + return ''; + } + + /** + * Checks whether block should be rendered + * basing on TransparentInterface presence in checkout session + * + * @return bool + */ + protected function shouldRender() + { + $quote = $this->checkoutSession->getQuote(); + if ($quote) { + $payment = $quote->getPayment(); + return $payment && $payment->getMethodInstance() instanceof TransparentInterface; + } + + return false; + } + + /** + * Initializes method + * + * @return void + */ + protected function initializeMethod() + { + $this->setData( + 'method', + $this->checkoutSession + ->getQuote() + ->getPayment() + ->getMethodInstance() + ); + } + + /** + * Parent rendering wrapper + * + * @return string + */ + protected function processHtml() + { + $this->initializeMethod(); + return parent::_toHtml(); + } + + /** + * Get type of request + * + * @return bool + */ + public function isAjaxRequest() + { + return $this->getRequest()->getParam('isAjax'); + } + + /** + * Get delimiter for date + * + * @return string + */ + public function getDateDelim() + { + return $this->getMethodConfigData('date_delim'); + } + + /** + * Get map of cc_code, cc_num, cc_expdate for gateway + * Returns json formatted string + * + * @return string + */ + public function getCardFieldsMap() + { + $keys = ['cccvv', 'ccexpdate', 'ccnum']; + $ccfields = array_combine($keys, explode(',', $this->getMethodConfigData('ccfields'))); + return json_encode($ccfields); + } + + /** + * Retrieve place order url on front + * + * @return string + */ + public function getOrderUrl() + { + return $this->_urlBuilder->getUrl( + $this->getMethodConfigData('place_order_url'), + [ + '_secure' => $this->getRequest()->isSecure() + ] + ); + } + + /** + * Retrieve gateway url + * + * @return string + */ + public function getCgiUrl() + { + return (bool)$this->getMethodConfigData('sandbox_flag') + ? $this->getMethodConfigData('cgi_url_test_mode') + : $this->getMethodConfigData('cgi_url'); + } + + /** + * Retrieve config data value by field name + * + * @param string $fieldName + * @return mixed + */ + public function getMethodConfigData($fieldName) + { + return $this->getMethod()->getConfigInterface()->getConfigValue($fieldName); + } + + /** + * Returns transparent method service + * + * @return TransparentInterface + * @throws LocalizedException + */ + public function getMethod() + { + $method = parent::getMethod(); + + if (!$method instanceof TransparentInterface) { + throw new LocalizedException( + __('We cannot retrieve the transparent payment method model object.') + ); + } + return $method; + } +} diff --git a/app/code/Magento/Payment/Block/Transparent/Iframe.php b/app/code/Magento/Payment/Block/Transparent/Iframe.php new file mode 100644 index 0000000000000000000000000000000000000000..3070173f92b36c0bae20d66aadce8981b7c322af --- /dev/null +++ b/app/code/Magento/Payment/Block/Transparent/Iframe.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Block\Transparent; + +/** + * Iframe block for register specific params in layout + * + * @author Magento Core Team <core@magentocommerce.com> + */ +class Iframe extends \Magento\Framework\View\Element\Template +{ + /** + * Core registry + * + * @var \Magento\Framework\Registry + */ + protected $coreRegistry; + + /** + * Constructor + * + * @param \Magento\Framework\View\Element\Template\Context $context + * @param \Magento\Framework\Registry $registry + * @param array $data + */ + public function __construct( + \Magento\Framework\View\Element\Template\Context $context, + \Magento\Framework\Registry $registry, + array $data = [] + ) { + $this->coreRegistry = $registry; + parent::__construct($context, $data); + } + + /** + * Preparing layout + * + * @return $this + */ + protected function _prepareLayout() + { + if ($this->hasRegistryKey()) { + $params = $this->coreRegistry->registry($this->getRegistryKey()); + $this->setParams($params); + } + return parent::_prepareLayout(); + } +} diff --git a/app/code/Magento/Payment/Block/Transparent/Info.php b/app/code/Magento/Payment/Block/Transparent/Info.php new file mode 100644 index 0000000000000000000000000000000000000000..af21b0e1758a59f2a7c3e9adb1b5905de346cd89 --- /dev/null +++ b/app/code/Magento/Payment/Block/Transparent/Info.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Block\Transparent; + +/** + * Class Info. Payment Information block used for transparent redirect feature + * @package Magento\Payment\Block\Transparent + */ +class Info extends \Magento\Framework\View\Element\Template +{ + /** + * @var string + */ + protected $_template = 'Magento_Payment::transparent/info.phtml'; +} diff --git a/app/code/Magento/Payment/Model/Method/AbstractMethod.php b/app/code/Magento/Payment/Model/Method/AbstractMethod.php index e316982a1be7081f470bc8cb2493d19ea0debfea..5a3a5a8b46262889fcd8a574a8b2fffb2a26f61c 100644 --- a/app/code/Magento/Payment/Model/Method/AbstractMethod.php +++ b/app/code/Magento/Payment/Model/Method/AbstractMethod.php @@ -254,6 +254,20 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl $this->_scopeConfig = $scopeConfig; $this->_eventManager = $context->getEventDispatcher(); $this->logger = $context->getLogger(); + $this->initializeData($data); + } + + /** + * Initializes injected data + * + * @param array $data + * @return void + */ + protected function initializeData($data = []) + { + if (!empty($data['formBlockType'])) { + $this->_formBlockType = $data['formBlockType']; + } } /** diff --git a/app/code/Magento/Payment/Model/Method/ConfigInterface.php b/app/code/Magento/Payment/Model/Method/ConfigInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..600f4fdb53a8c0eada317308eeda14a9a26907ee --- /dev/null +++ b/app/code/Magento/Payment/Model/Method/ConfigInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Model\Method; + +/** + * Interface for payment methods config + * + * @author Magento Core Team <core@magentocommerce.com> + */ +interface ConfigInterface +{ + /** + * Config field getter + * The specified key can be either in camelCase or under_score format + * + * @param string $key + * @return mixed + */ + public function getConfigValue($key); +} diff --git a/app/code/Magento/Payment/Model/Method/Logger.php b/app/code/Magento/Payment/Model/Method/Logger.php new file mode 100644 index 0000000000000000000000000000000000000000..9c9e54e5e23636527f64eaff58997e6bb0de70c7 --- /dev/null +++ b/app/code/Magento/Payment/Model/Method/Logger.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Model\Method; + +use Psr\Log\LoggerInterface; + +/** + * Class Logger for payment related information (request, response, etc.) which is used for debug + * + * @author Magento Core Team <core@magentocommerce.com> + */ +class Logger +{ + /** + * @var LoggerInterface + */ + protected $logger; + + /** + * @param LoggerInterface $logger + */ + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; + } + + /** + * Logs payment related information used for debug + * + * @param mixed $logData + * @param ConfigInterface $config + * + * @return void + */ + public function debug($logData, ConfigInterface $config) + { + if ($config->getConfigValue('debug')) { + $this->logger->debug(var_export($logData, true)); + } + } +} diff --git a/app/code/Magento/Payment/Model/Method/Online/GatewayInterface.php b/app/code/Magento/Payment/Model/Method/Online/GatewayInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..4a99a7e8308758e368ad364463673f4828e2ca0e --- /dev/null +++ b/app/code/Magento/Payment/Model/Method/Online/GatewayInterface.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Model\Method\Online; + +use Magento\Framework\Object; +use Magento\Payment\Model\Method\ConfigInterface; + +/** + * Gateway interface for online payment methods + * + * @author Magento Core Team <core@magentocommerce.com> + */ +interface GatewayInterface +{ + /** + * Post request to gateway and return response + * + * @param Object $request + * @param ConfigInterface $config + * + * @return Object + * + * @throws \Exception + */ + public function postRequest(Object $request, ConfigInterface $config); +} diff --git a/app/code/Magento/Payment/Model/Method/TransparentInterface.php b/app/code/Magento/Payment/Model/Method/TransparentInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..eebb8594cc2ea9a0259edd508aef77bd6fa1c9b2 --- /dev/null +++ b/app/code/Magento/Payment/Model/Method/TransparentInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Model\Method; + +use Magento\Payment\Model\MethodInterface; + +/** + * Interface TransparentInterface need to be implemented by Payment Method service + * which supports transparent redirect feature + * @package Magento\Payment\Model\Method + */ +interface TransparentInterface extends MethodInterface +{ + /** + * Returns payment method configured config + * + * @return ConfigInterface + */ + public function getConfigInterface(); +} diff --git a/app/code/Magento/Payment/Test/Unit/Block/Adminhtml/Transparent/FormTest.php b/app/code/Magento/Payment/Test/Unit/Block/Adminhtml/Transparent/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3281e616a649bd16ce9293069d052a965e380c5d --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Block/Adminhtml/Transparent/FormTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Block\Adminhtml\Transparent; + +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Object; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\UrlInterface; +use Magento\Payment\Model\Method\TransparentInterface; + +class FormTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var FormTesting | \PHPUnit_Framework_MockObject_MockObject + */ + private $form; + + /** + * @var TransparentInterface | \PHPUnit_Framework_MockObject_MockObject + */ + private $methodMock; + + /** + * @var \Magento\Checkout\Model\Session | \PHPUnit_Framework_MockObject_MockObject + */ + private $checkoutSessionMock; + + protected function setUp() + { + $objectManagerHelper = new ObjectManager($this); + + $this->requestMock = $this->getMockBuilder('\Magento\Framework\App\RequestInterface') + ->setMethods(['getParam']) + ->getMockForAbstractClass(); + + $this->urlBuilderMock = $this->getMockBuilder('\Magento\Framework\UrlInterface') + ->setMethods(['getUrl']) + ->getMockForAbstractClass(); + + $context = $objectManagerHelper->getObject('Magento\Framework\View\Element\Template\Context'); + + $this->methodMock = $this->getMockBuilder('Magento\Payment\Model\Method\TransparentInterface') + ->getMock(); + + $this->checkoutSessionMock = $this->getMockBuilder('Magento\Checkout\Model\Session') + ->setMethods([]) + ->disableOriginalConstructor() + ->getMock(); + + $paymentConfigMock = $this->getMockBuilder('Magento\Payment\Model\Config') + ->setMethods([]) + ->disableOriginalConstructor() + ->getMock(); + + $this->form = new FormTesting( + $context, + $paymentConfigMock, + $this->checkoutSessionMock + ); + } + + public function testToHtmlShouldRender() + { + $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + $paymentMock = $this->getMockBuilder('Magento\Quote\Model\Quote\Payment') + ->disableOriginalConstructor() + ->getMock(); + + $this->checkoutSessionMock->expects($this->never()) + ->method('getQuote') + ->willReturn($quoteMock); + $quoteMock->expects($this->never()) + ->method('getPayment') + ->willReturn($paymentMock); + $paymentMock->expects($this->never()) + ->method('getMethodInstance') + ->willReturn($this->methodMock); + + $this->form->toHtml(); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Block/Adminhtml/Transparent/FormTesting.php b/app/code/Magento/Payment/Test/Unit/Block/Adminhtml/Transparent/FormTesting.php new file mode 100644 index 0000000000000000000000000000000000000000..e48bf8f6a57e7cea7576db24e565c4b1e2a2b0bf --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Block/Adminhtml/Transparent/FormTesting.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Block\Adminhtml\Transparent; + +use Magento\Payment\Block\Adminhtml\Transparent\Form; + +/** + * Class FormTesting extended test class, used to substitute calls to parent methods + * @package Magento\Payment\Test\Unit\Block\Adminhtml\Transparent + */ +class FormTesting extends Form +{ + /** + * Return values for processHtml() method + */ + const PROCESS_HTML_RESULT = 'parent_result'; + + /** + * {inheritdoc} + */ + protected function processHtml() + { + return self::PROCESS_HTML_RESULT; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Block/FormTest.php b/app/code/Magento/Payment/Test/Unit/Block/FormTest.php index 2db84edbdfd599c017242715d510240ce944a5f7..9f01df530fa1520c38e79312f2f309de3b4df336 100644 --- a/app/code/Magento/Payment/Test/Unit/Block/FormTest.php +++ b/app/code/Magento/Payment/Test/Unit/Block/FormTest.php @@ -119,4 +119,12 @@ class FormTest extends \PHPUnit_Framework_TestCase ] ]; } + + public function testSetMethod() + { + $methodInterfaceMock = $this->getMockBuilder('\Magento\Payment\Model\MethodInterface') + ->getMockForAbstractClass(); + + $this->assertSame($this->_object, $this->_object->setMethod($methodInterfaceMock)); + } } diff --git a/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTest.php b/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b361cc1881eec8ae1c463dbf7b2ead8d1ce39a19 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTest.php @@ -0,0 +1,301 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Block\Transparent; + +use Magento\Checkout\Model\Session; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Object; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\UrlInterface; +use Magento\Payment\Model\Method\TransparentInterface; + +class FormTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var FormTesting | \PHPUnit_Framework_MockObject_MockObject + */ + private $form; + + /** + * @var RequestInterface | \PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; + + /** + * @var UrlInterface | \PHPUnit_Framework_MockObject_MockObject + */ + private $urlBuilderMock; + + /** + * @var TransparentInterface | \PHPUnit_Framework_MockObject_MockObject + */ + private $methodMock; + + /** + * @var Session | \PHPUnit_Framework_MockObject_MockObject + */ + private $checkoutSessionMock; + + protected function setUp() + { + $objectManagerHelper = new ObjectManager($this); + + $this->requestMock = $this->getMockBuilder('\Magento\Framework\App\RequestInterface') + ->setMethods(['getParam']) + ->getMockForAbstractClass(); + + $this->urlBuilderMock = $this->getMockBuilder('\Magento\Framework\UrlInterface') + ->setMethods(['getUrl']) + ->getMockForAbstractClass(); + + $context = $objectManagerHelper->getObject( + 'Magento\Framework\View\Element\Template\Context', + [ + 'request' => $this->requestMock, + 'urlBuilder' => $this->urlBuilderMock + ] + ); + + $this->methodMock = $this->getMockBuilder('Magento\Payment\Model\Method\TransparentInterface') + ->getMock(); + + $this->checkoutSessionMock = $this->getMockBuilder('Magento\Checkout\Model\Session') + ->setMethods([]) + ->disableOriginalConstructor() + ->getMock(); + + $paymentConfigMock = $this->getMockBuilder('Magento\Payment\Model\Config') + ->setMethods([]) + ->disableOriginalConstructor() + ->getMock(); + + $this->form = new FormTesting( + $context, + $paymentConfigMock, + $this->checkoutSessionMock + ); + } + + public function testIsAjaxRequest() + { + $this->requestMock->expects($this->exactly(2)) + ->method('getParam') + ->with('isAjax') + ->willReturnOnConsecutiveCalls(true, false); + + $this->assertTrue($this->form->isAjaxRequest()); + $this->assertFalse($this->form->isAjaxRequest()); + } + + /** + * @param string $fieldName + * @param mixed $fieldValue + * @param mixed $expected + * + * @dataProvider getMethodConfigDataDataProvider + */ + public function testGetMethodConfigData($fieldName, $fieldValue, $expected) + { + $this->initializeMethodWithConfigMock([[$fieldName, $fieldValue]]); + + $this->form->setMethod($this->methodMock); + + $this->assertEquals($expected, $this->form->getMethodConfigData($fieldName)); + } + + /** + * Initializes method mock with config mock + * + * @param array $configMap + */ + private function initializeMethodWithConfigMock(array $configMap = []) + { + $configInterface = $this->getMockBuilder('Magento\Payment\Model\Method\ConfigInterface') + ->getMock(); + + $configInterface->expects($this->any()) + ->method('getConfigValue') + ->willReturnMap($configMap); + + $this->methodMock->expects($this->any()) + ->method('getConfigInterface') + ->willReturn($configInterface); + } + + /** + * Data provider for testGetMethodConfigData + * + * @see testGetMethodConfigData + * + * @case #1 Set string value + * @case #2 Set boolean value + * + * @return array + */ + public function getMethodConfigDataDataProvider() + { + return [ + ['gateway_name', 'payment_gateway', 'payment_gateway'], + ['sandbox_flag', true, true], + ]; + } + + /** + * @dataProvider getCgiUrlDataProvider + * + * @param $sandboxFlag + * @param $cgiUrlTestMode + * @param $cgiUrl + * @param $expectedUrl + */ + public function testGetCgiUrl($sandboxFlag, $cgiUrlTestMode, $cgiUrl, $expectedUrl) + { + $this->initializeMethodWithConfigMock( + [ + ['sandbox_flag', $sandboxFlag], + ['cgi_url_test_mode', $cgiUrlTestMode], + ['cgi_url', $cgiUrl] + ] + ); + + $this->form->setMethod($this->methodMock); + + $this->assertEquals($expectedUrl, $this->form->getCgiUrl()); + } + + /** + * Data provider for testGetCgiUrl + * + * @see testGetCgiUrl + * + * @case #1 The sandboxFlag is 1 we expected cgi_url_test_mode_value + * @case #2 The sandboxFlag is 0 we expected cgi_url_value + * + * @return array + */ + public function getCgiUrlDataProvider() + { + return [ + [ + 1, + 'cgi_url_test_mode_value', + 'cgi_url_value', + 'cgi_url_test_mode_value' + ], + [ + 0, + 'cgi_url_test_mode_value', + 'cgi_url_value', + 'cgi_url_value' + ], + ]; + } + + public function testGetOrderUrl() + { + $orderUrlPattern = 'order_url'; + $builtOrderUrl = 'built_url'; + $this->initializeMethodWithConfigMock([['place_order_url', $orderUrlPattern]]); + + $this->urlBuilderMock->expects($this->once()) + ->method('getUrl') + ->with($orderUrlPattern) + ->willReturn($builtOrderUrl); + + $this->form->setMethod($this->methodMock); + + $this->assertEquals($builtOrderUrl, $this->form->getOrderUrl()); + } + + public function testGetDateDelim() + { + $dateDelimiter = '/'; + $this->initializeMethodWithConfigMock([['date_delim', $dateDelimiter]]); + + $this->form->setMethod($this->methodMock); + + $this->assertEquals($dateDelimiter, $this->form->getDateDelim()); + } + + public function testGetCardFieldsMap() + { + $ccfields = 'x_card_code,x_exp_date,x_card_num'; + $this->initializeMethodWithConfigMock([['ccfields', $ccfields]]); + + $this->form->setMethod($this->methodMock); + + $expected = json_encode(['cccvv' => 'x_card_code', 'ccexpdate' => 'x_exp_date', 'ccnum' => 'x_card_num']); + + $this->assertEquals($expected, $this->form->getCardFieldsMap()); + } + + public function testToHtmlShouldRender() + { + $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + $paymentMock = $this->getMockBuilder('Magento\Quote\Model\Quote\Payment') + ->disableOriginalConstructor() + ->getMock(); + + $this->checkoutSessionMock->expects($this->once()) + ->method('getQuote') + ->willReturn($quoteMock); + $quoteMock->expects($this->once()) + ->method('getPayment') + ->willReturn($paymentMock); + $paymentMock->expects($this->once()) + ->method('getMethodInstance') + ->willReturn($this->methodMock); + + $this->form->toHtml(); + } + + public function testToHtmlShouldNotRenderEmptyQuote() + { + $this->checkoutSessionMock->expects($this->once()) + ->method('getQuote') + ->willReturn(null); + + $this->assertEmpty($this->form->toHtml()); + } + + public function testToHtmlShouldNotRenderEmptyPayment() + { + $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + + $this->checkoutSessionMock->expects($this->once()) + ->method('getQuote') + ->willReturn($quoteMock); + $quoteMock->expects($this->once()) + ->method('getPayment') + ->willReturn(null); + + $this->assertEmpty($this->form->toHtml()); + } + + public function testGetMethodSuccess() + { + $this->form->setMethod($this->methodMock); + $this->assertSame($this->methodMock, $this->form->getMethod()); + } + + public function testGetMethodNotTransparentInterface() + { + $this->setExpectedException( + 'Magento\Framework\Exception\LocalizedException', + __('We cannot retrieve the transparent payment method model object.') + ); + + $methodMock = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') + ->getMockForAbstractClass(); + + $this->form->setMethod($methodMock); + $this->form->getMethod(); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTesting.php b/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTesting.php new file mode 100644 index 0000000000000000000000000000000000000000..cdeb6a8b5fc76d2fe77e824c3b1b9b56f6582274 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTesting.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Block\Transparent; + +use Magento\Payment\Block\Transparent\Form; + +/** + * Class FormTesting extended test class, used to substitute calls to parent methods + * @package Magento\Payment\Test\Unit\Block\Transparent + */ +class FormTesting extends Form +{ + /** + * Return values for processHtml() method + */ + const PROCESS_HTML_RESULT = 'parent_result'; + + /** + * {inheritdoc} + */ + protected function processHtml() + { + return self::PROCESS_HTML_RESULT; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Model/Method/LoggerTest.php b/app/code/Magento/Payment/Test/Unit/Model/Method/LoggerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..75efef237b33a53a318e56ca50920d21f644418f --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Model/Method/LoggerTest.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Payment\Test\Unit\Model\Method; + +use Magento\Payment\Model\Method\ConfigInterface; +use Magento\Payment\Model\Method\Logger; +use Psr\Log\LoggerInterface; + +class LoggerTest extends \PHPUnit_Framework_TestCase +{ + /** @var Logger | \PHPUnit_Framework_MockObject_MockObject */ + private $logger; + + /** @var LoggerInterface | \PHPUnit_Framework_MockObject_MockObject */ + private $loggerMock; + + /** @var ConfigInterface | \PHPUnit_Framework_MockObject_MockObject */ + private $configMock; + + protected function setUp() + { + $this->loggerMock = $this->getMockForAbstractClass('Psr\Log\LoggerInterface'); + $this->configMock = $this->getMockForAbstractClass('Magento\Payment\Model\Method\ConfigInterface'); + + $this->logger = new Logger($this->loggerMock); + } + + public function testDebugOn() + { + $this->configMock->expects($this->once()) + ->method('getConfigValue') + ->with('debug') + ->willReturn(true); + $this->loggerMock->expects($this->once()) + ->method('debug') + ->with("'test_value'"); + + $this->logger->debug('test_value', $this->configMock); + } + + public function testDebugOff() + { + $this->configMock->expects($this->once()) + ->method('getConfigValue') + ->with('debug') + ->willReturn(false); + $this->loggerMock->expects($this->never()) + ->method('debug'); + + $this->logger->debug('', $this->configMock); + } +} diff --git a/app/code/Magento/Payment/composer.json b/app/code/Magento/Payment/composer.json index b4e88d864a2b2c0868d6bd2cb685f0b81bcb0d4d..f765253fd15845aba891a6d80232c3d0599a3b6d 100644 --- a/app/code/Magento/Payment/composer.json +++ b/app/code/Magento/Payment/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-centinel": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-centinel": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml new file mode 100644 index 0000000000000000000000000000000000000000..e9632aa0f89155238a8a659b660687a2bc4ce743 --- /dev/null +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml @@ -0,0 +1,94 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +?> +<?php +// @codingStandardsIgnoreFile + +/** @var \Magento\Payment\Block\Transparent\Form $block*/ +$code = $block->getMethodCode(); +?> + +<!-- IFRAME for request to Payment Gateway --> +<iframe id="<?php echo $code ?>-transparent-iframe" data-container="<?php echo $code ?>-transparent-iframe" allowtransparency="true" frameborder="0" name="iframeTransparent" style="display:none;width:100%;background-color:transparent" src="<?php echo $block->getViewFileUrl('blank.html') ?>"></iframe> +<div id="payment_form_<?php echo $code ?>" + data-mage-init='{ + "transparent":{ + "controller":"<?php echo $block->getRequest()->getControllerName() ?>", + "gateway":"<?php echo $block->getMethodCode() ?>", + "dateDelim":"<?php echo $block->getDateDelim() ?>", + "cardFieldsMap":<?php echo $block->getCardFieldsMap() ?>, + "orderSaveUrl":"<?php echo $block->getOrderUrl() ?>", + "cgiUrl":"<?php echo $block->getCgiUrl() ?>", + "nativeAction":"<?php echo $block->getUrl('*/*/save', ['_secure' => $block->getRequest()->isSecure()]) ?>" + }, "validation":[]}' + style="display:none;"> + + <div class="field required type"> + <label for="<?php echo $code ?>_cc_type" class="label"><span><?php echo __('Credit Card Type') ?></span></label> + <div class="control"> + <select id="<?php echo $code ?>_cc_type" data-container="<?php echo $code ?>-cc-type" name="payment[cc_type]" data-validate='{required:true, "validate-cc-type-select":"#<?php echo $code ?>_cc_number"}'> + <option value=""><?php echo __('--Please Select--')?></option> + <?php $_ccType = $block->getInfoData('cc_type') ?> + <?php foreach ($block->getCcAvailableTypes() as $_typeCode => $_typeName): ?> + <option value="<?php echo $_typeCode ?>"<?php if ($_typeCode == $_ccType): ?> selected="selected"<?php endif ?>><?php echo $_typeName ?></option> + <?php endforeach ?> + </select> + </div> + </div> + + <div class="field required number"> + <label for="<?php echo $code ?>_cc_number" class="label"><span><?php echo __('Credit Card Number') ?></span></label> + <div class="control"> + <input type="number" id="<?php echo $code ?>_cc_number" data-container="<?php echo $code ?>-cc-number" name="payment[cc_number]" title="<?php echo __('Credit Card Number') ?>" class="input-text" value="" data-validate='{"required-number":true, "validate-cc-number":"#<?php echo $code ?>_cc_type", "validate-cc-type":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/> + </div> + </div> + + <div class="field required date" id="<?php echo $code ?>_cc_type_exp_div"> + <label for="<?php echo $code ?>_expiration" class="label"><span><?php echo __('Expiration Date') ?></span></label> + <div class="control"> + <div class="fields group group-2"> + <div class="field no-label month"> + <div class="control"> + <select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]" data-container="<?php echo $code ?>-cc-month" class="month" data-validate='{required:true, "validate-cc-exp":"#<?php echo $code ?>_expiration_yr"}'> + <?php $_ccExpMonth = $block->getInfoData('cc_exp_month') ?> + <?php foreach ($block->getCcMonths() as $k => $v): ?> + <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> + <?php endforeach ?> + </select> + </div> + </div> + <div class="field no-label year"> + <div class="control"> + <?php $_ccExpYear = $block->getInfoData('cc_exp_year') ?> + <select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]" class="year" data-container="<?php echo $code ?>-cc-year" data-validate='{required:true}'> + <?php foreach ($block->getCcYears() as $k => $v): ?> + <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> + <?php endforeach ?> + </select> + </div> + </div> + </div> + </div> + </div> + <?php if ($block->hasVerification()): ?> + <div class="field required cvv" id="<?php echo $code ?>_cc_type_cvv_div"> + <label for="<?php echo $code ?>_cc_cid" class="label"><span><?php echo __('Card Verification Number') ?></span></label> + <div class="control"> + <input type="number" title="<?php echo __('Card Verification Number') ?>" data-container="<?php echo $code ?>-cc-cvv" class="input-text cvv" id="<?php echo $code ?>_cc_cid" name="payment[cc_cid]" value="" data-validate='{"required-number":true, "validate-cc-cvn":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/> + </div> + </div> + <?php endif; ?> + <?php echo $block->getChildHtml() ?> +</div> + +<script> + /** + * Disable card server validation in admin + */ + require(["Magento_Sales/order/create/form"], function(){ + order.addExcludedPaymentMethod('<?php echo $code ?>'); + }); +</script> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/iframe.phtml new file mode 100644 index 0000000000000000000000000000000000000000..943767e9b80556510bc3d2aa637da38fa9a5ea44 --- /dev/null +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/iframe.phtml @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +$params = $block->getParams(); + +?> +<html> +<head> +<script> +<?php if (isset($params['redirect'])): ?> + window.location="<?php echo $block->escapeUrl($params['redirect']) ?>"; +<?php elseif (isset($params['redirect_parent'])): ?> + window.top.location="<?php echo $block->escapeUrl($params['redirect_parent']) ?>"; +<?php elseif (isset($params['error_msg'])): ?> + window.top.alert(<?php echo $block->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($params['error_msg']) ?>); +<?php elseif (isset($params['order_success'])): ?> + window.top.location = "<?php echo $params['order_success'] ?>"; +<?php else: ?> + var require = window.top.require; + require(['jquery'], function($) { + $('#edit_form').trigger('processStop'); + + $("input[name='payment[cc_number]']").prop('disabled', true); + $("select[name='payment[cc_type]']").prop('disabled', true); + $("select[name='payment[cc_exp_month]']").prop('disabled', true); + $("select[name='payment[cc_exp_year]']").prop('disabled', true); + $("input[name='payment[cc_cid]']").prop('disabled', true); + + $('#edit_form').trigger('realOrder'); + }); +<?php endif; ?> +</script> +</head> +<body> +</body> +</html> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml new file mode 100644 index 0000000000000000000000000000000000000000..badfd92d13a478cb0c409eccb4f9f3af9210e150 --- /dev/null +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * @see \Magento\Payment\Block\Transparent\Info + */ +?> +<fieldset id="payment_form_<?php echo $block->getMethodCode() ?>" style="display:none" class="fieldset items redirect"> + <div><?php echo __('You\'ll be asked for your payment details before placing an order.') ?></div> +</fieldset> diff --git a/app/code/Magento/Payment/view/adminhtml/web/transparent.js b/app/code/Magento/Payment/view/adminhtml/web/transparent.js new file mode 100644 index 0000000000000000000000000000000000000000..1317880d7f062c08ebe1c1fee96be951796b1a53 --- /dev/null +++ b/app/code/Magento/Payment/view/adminhtml/web/transparent.js @@ -0,0 +1,165 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + "jquery", + "mage/template", + "jquery/ui" +], function($, mageTemplate){ + "use strict"; + + $.widget('mage.transparent', { + options: { + hiddenFormTmpl: + '<form target="<%= data.target %>" action="<%= data.action %>" method="POST" hidden enctype="application/x-www-form-urlencoded" class="no-display">' + + '<% _.each(data.inputs, function(val, key){ %>' + + '<input value="<%= val %>" name="<%= key %>" type="hidden">' + + '<% }); %>' + + '</form>', + cgiUrl: null, + orderSaveUrl: null, + controller: null, + gateway: null, + dateDelim: null, + cardFieldsMap: null + }, + + _create: function() { + var prepare = function (event, method) { + if (method === this.options.gateway) { + $('#edit_form') + .off('submitOrder') + .on('submitOrder', this._orderSave.bind(this)) + } + }; + this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl); + jQuery('#edit_form').on('changePaymentMethod', prepare.bind(this)); + + jQuery('#edit_form').trigger( + 'changePaymentMethod', + [ + jQuery('#edit_form').find(':radio[name="payment[method]"]:checked').val() + ] + ); + }, + + /** + * handler for Place Order button to call gateway for credit card validation + * Save order and generate post data for gateway call + * @private + */ + _orderSave: function() { + var postData = "form_key="+FORM_KEY; + $.ajax({ + url: this.options.orderSaveUrl, + type: 'post', + context: this, + data: postData, + dataType: 'json', + success: function(response) { + if (response.success && response[this.options.gateway]) { + this._postPaymentToGateway(response); + } else { + this._processErrors(response); + } + } + }); + }, + + /** + * Post data to gateway for credit card validation + * @param response + * @private + */ + _postPaymentToGateway: function(response) { + var data, + tmpl, + iframe; + + data = this._preparePaymentData(response); + var iframeSelector = '[data-container="' + this.options.gateway + '-transparent-iframe"]'; + + tmpl = this.hiddenFormTmpl({ + data: { + target: $(iframeSelector).attr('name'), + action: this.options.cgiUrl, + inputs: data + } + }); + + iframe = $(iframeSelector) + .on('submit', function(event){ + event.stopPropagation(); + }); + $(tmpl).appendTo(iframe).submit(); + iframe.html(''); + }, + + /** + * Add credit card fields to post data for gateway + * + * @param response + * @private + */ + _preparePaymentData: function(response) { + var ccfields, + data, + preparedata; + + data = response[this.options.gateway].fields; + ccfields = this.options.cardFieldsMap; + + if (this.element.find('[data-container="' + this.options.gateway + '-cc-cvv"]').length) { + data[ccfields.cccvv] = this.element.find( + '[data-container="' + this.options.gateway + '-cc-cvv"]' + ).val(); + } + preparedata = this._prepareExpDate(); + data[ccfields.ccexpdate] = preparedata.month + this.options.dateDelim + preparedata.year; + data[ccfields.ccnum] = this.element.find( + '[data-container="' + this.options.gateway + '-cc-number"]' + ).val(); + return data; + }, + + /** + * Grab Month and Year into one + * @returns {object} + * @private + */ + _prepareExpDate: function() { + var year = this.element.find('[data-container="' + this.options.gateway + '-cc-year"]').val(), + month = parseInt( + this.element.find('[data-container="' + this.options.gateway + '-cc-month"]').val() + , 10 + ); + if (year.length > 2) { + year = year.substring(2); + } + if (month < 10) { + month = '0' + month; + } + return {month: month, year: year}; + }, + + /** + * Processing errors + * + * @param response + * @private + */ + _processErrors: function (response) { + var msg = response.error_messages; + if (typeof (msg) === 'object') { + alert(msg.join("\n")); + } + if (msg) { + alert(msg); + } + } + }); + + return $.mage.transparent; +}); diff --git a/app/code/Magento/Ui/view/base/layout/default.xml b/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_review.xml similarity index 52% rename from app/code/Magento/Ui/view/base/layout/default.xml rename to app/code/Magento/Payment/view/frontend/layout/checkout_onepage_review.xml index 289b9006c48b5014637cea71d5f054d2ba733e70..8bdab785e571d24a7092c52b5ac420fe697dc1d5 100644 --- a/app/code/Magento/Ui/view/base/layout/default.xml +++ b/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_review.xml @@ -7,11 +7,11 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> - <referenceContainer name="footer"> - <block class="Magento\Ui\Context\DataProvider" name="ui.global.config" after="-"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::context/default.phtml</argument> - </arguments> + <referenceContainer name="checkout.onepage.review.info.items.after"> + <block class="Magento\Payment\Block\Transparent\Form" name="payment.form.transparent"> + <action method="setTemplate"> + <argument name="template" xsi:type="string">Magento_Payment::transparent/form.phtml</argument> + </action> </block> </referenceContainer> </body> diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml new file mode 100644 index 0000000000000000000000000000000000000000..5a4e8c63822a4ba2097d266cfd99232c67378ba6 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +/** @var \Magento\Payment\Block\Transparent\Form $block */ +$code = $block->getMethodCode(); +?> + +<!-- IFRAME for request to Payment Gateway --> +<iframe width="0" height="0" id="<?php echo $code ?>-transparent-iframe" data-container="<?php echo $code ?>-transparent-iframe" allowtransparency="true" frameborder="0" name="iframeTransparent" style="display:none;width:100%;background-color:transparent" src="<?php echo $block->getViewFileUrl('blank.html') ?>"></iframe> +<form class="form" id="co-transparent-form" action="#" method="post" data-mage-init='{ + "transparent":{ + "controller":"<?php echo $block->getRequest()->getControllerName() ?>", + "gateway":"<?php echo $code ?>", + "orderSaveUrl":"<?php echo $block->getOrderUrl() ?>", + "cgiUrl":"<?php echo $block->getCgiUrl() ?>", + "dateDelim":"<?php echo $block->getDateDelim() ?>", + "cardFieldsMap":<?php echo $block->getCardFieldsMap() ?>, + "nativeAction":"<?php echo $block->getUrl('checkout/onepage/saveOrder', ['_secure' => $block->getRequest()->isSecure()]) ?>" + }, "validation":[]}'> + <fieldset class="fieldset ccard <?php echo $code ?>" id="payment_form_<?php echo $code ?>"> + <legend class="legend"><span><?php echo __('Credit Card Information') ?></span></legend><br /> + <div class="field required type"> + <label for="<?php echo $code ?>_cc_type" class="label"><span><?php echo __('Credit Card Type') ?></span></label> + <div class="control"> + <select id="<?php echo $code ?>_cc_type" data-container="<?php echo $code ?>-cc-type" name="payment[cc_type]" data-validate='{required:true, "validate-cc-type-select":"#<?php echo $code ?>_cc_number"}'> + <option value=""><?php echo __('--Please Select--')?></option> + <?php $_ccType = $block->getInfoData('cc_type') ?> + <?php foreach ($block->getCcAvailableTypes() as $_typeCode => $_typeName): ?> + <option value="<?php echo $_typeCode ?>"<?php if ($_typeCode == $_ccType): ?> selected="selected"<?php endif ?>><?php echo $_typeName ?></option> + <?php endforeach ?> + </select> + </div> + </div> + <div class="field required number"> + <label for="<?php echo $code ?>_cc_number" class="label"><span><?php echo __('Credit Card Number') ?></span></label> + <div class="control"> + <input type="number" id="<?php echo $code ?>_cc_number" data-container="<?php echo $code ?>-cc-number" name="payment[cc_number]" title="<?php echo __('Credit Card Number') ?>" class="input-text" value="" data-validate='{"required-number":true, "validate-cc-number":"#<?php echo $code ?>_cc_type", "validate-cc-type":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/> + </div> + </div> + <div class="field required date" id="<?php echo $code ?>_cc_type_exp_div"> + <label for="<?php echo $code ?>_expiration" class="label"><span><?php echo __('Expiration Date') ?></span></label> + <div class="control"> + <div class="fields group group-2"> + <div class="field no-label month"> + <div class="control"> + <select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]" data-container="<?php echo $code ?>-cc-month" class="month" data-validate='{required:true, "validate-cc-exp":"#<?php echo $code ?>_expiration_yr"}'> + <?php $ccExpMonth = $block->getInfoData('cc_exp_month') ?> + <?php foreach ($block->getCcMonths() as $k => $v): ?> + <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> + <?php endforeach ?> + </select> + </div> + </div> + <div class="field no-label year"> + <div class="control"> + <select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]" class="year" data-container="<?php echo $code ?>-cc-year" data-validate='{required:true}'> + <?php $ccExpYear = $block->getInfoData('cc_exp_year') ?> + <?php foreach ($block->getCcYears() as $k => $v): ?> + <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> + <?php endforeach ?> + </select> + </div> + </div> + </div> + </div> + </div> + <?php if ($block->hasVerification()): ?> + <div class="field required cvv" id="<?php echo $code ?>_cc_type_cvv_div"> + <label for="<?php echo $code ?>_cc_cid" class="label"><span><?php echo __('Card Verification Number') ?></span></label> + <div class="control"> + <input type="number" title="<?php echo __('Card Verification Number') ?>" data-container="<?php echo $code ?>-cc-cvv" class="input-text cvv" id="<?php echo $code ?>_cc_cid" name="payment[cc_cid]" value="" data-validate='{"required-number":true, "validate-cc-cvn":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/> + <?php $_content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . '\" alt=\"' . __('Card Verification Number Visual Reference') . '\" title=\"' . __('Card Verification Number Visual Reference') . '\" />'; ?> + <div class="note"> + <a href="#" id="<?php echo $code ?>-cvv-what-is-this" class="action cvv" title="<?php echo $block->escapeHtml(__('What is this?'));?>" data-mage-init='{"tooltip": {"content": "<?php echo $_content ?>"}}'><span><?php echo __('What is this?') ?></span></a> + </div> + </div> + </div> + <?php endif; ?> + <?php echo $block->getChildHtml() ?> +</fieldset> +</form> diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml new file mode 100644 index 0000000000000000000000000000000000000000..d090920cb02945f4d00f34b66d6c65355e084007 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +/** @var \Magento\Payment\Block\Transparent\Iframe $block */ +$params = $block->getParams(); +?> +<html> + <head> + <script> + <?php if (isset($params['redirect'])): ?> + window.location="<?php echo $block->escapeUrl($params['redirect']) ?>"; + <?php elseif (isset($params['redirect_parent'])): ?> + window.top.location="<?php echo $block->escapeUrl($params['redirect_parent']) ?>"; + <?php elseif (isset($params['error_msg'])): ?> + window.top.alert(<?php echo $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($params['error_msg']) ?>); + <?php elseif (isset($params['order_success'])): ?> + window.top.location = "<?php echo $params['order_success'] ?>"; + <?php else: ?> + var require = window.top.require; + require(['jquery'], function($) { + $('#opc-review').trigger('hideAjaxLoader'); + $('#opc-review').trigger('saveOrder'); + }); + <?php endif; ?> + </script> + </head> + <body></body> +</html> diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml new file mode 100644 index 0000000000000000000000000000000000000000..badfd92d13a478cb0c409eccb4f9f3af9210e150 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * @see \Magento\Payment\Block\Transparent\Info + */ +?> +<fieldset id="payment_form_<?php echo $block->getMethodCode() ?>" style="display:none" class="fieldset items redirect"> + <div><?php echo __('You\'ll be asked for your payment details before placing an order.') ?></div> +</fieldset> diff --git a/app/code/Magento/Payment/view/frontend/web/transparent.js b/app/code/Magento/Payment/view/frontend/web/transparent.js new file mode 100644 index 0000000000000000000000000000000000000000..570772d6d430c67d6dcd4ea10325fade6d3407b0 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/transparent.js @@ -0,0 +1,154 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + "jquery", + "mage/template", + "jquery/ui" +], function($, mageTemplate){ + "use strict"; + + $.widget('mage.transparent', { + options: { + placeOrderSelector: '[data-role="review-save"]', + paymentFormSelector: '#co-payment-form', + updateSelectorPrefix: '#checkout-', + updateSelectorSuffix: '-load', + hiddenFormTmpl: + '<form target="<%= data.target %>" action="<%= data.action %>" method="POST" hidden enctype="application/x-www-form-urlencoded" class="no-display">' + + '<% _.each(data.inputs, function(val, key){ %>' + + '<input value="<%= val %>" name="<%= key %>" type="hidden">' + + '<% }); %>' + + '</form>', + reviewAgreementForm: '#checkout-agreements', + cgiUrl: null, + orderSaveUrl: null, + controller: null, + gateway: null, + dateDelim: null, + cardFieldsMap: null + }, + + _create: function() { + this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl); + $(this.options.placeOrderSelector) + .off('click') + .on('click', $.proxy(this._placeOrderHandler, this)); + }, + + /** + * handler for Place Order button to call gateway for credit card validation + * @return {Boolean} + * @private + */ + _placeOrderHandler: function() { + if (this.element.validation && this.element.validation('isValid')) { + this._orderSave(); + } + return false; + }, + + /** + * Save order and generate post data for gateway call + * @private + */ + _orderSave: function() { + var postData = $(this.options.paymentFormSelector).serialize(); + if ($(this.options.reviewAgreementForm).length) { + postData += '&' + $(this.options.reviewAgreementForm).serialize(); + } + postData += '&controller=' + this.options.controller; + $.ajax({ + url: this.options.orderSaveUrl, + type: 'post', + context: this, + data: postData, + dataType: 'json', + beforeSend: function() {this.element.trigger('showAjaxLoader');}, + success: function(response) { + var preparedData, + msg; + if (response.success && response[this.options.gateway]) { + preparedData = this._preparePaymentData( + response[this.options.gateway].fields, + this.options.cardFieldsMap + ); + this._postPaymentToGateway(preparedData); + } else { + msg = response.error_messages; + if (typeof (msg) === 'object') { + alert(msg.join("\n")); + } + if (msg) { + alert(msg); + } + } + } + }); + }, + + /** + * Post data to gateway for credit card validation + * @param data + * @private + */ + _postPaymentToGateway: function(data) { + var tmpl; + var iframeSelector = '[data-container="' + this.options.gateway + '-transparent-iframe"]'; + + tmpl = this.hiddenFormTmpl({ + data: { + target: $(iframeSelector).attr('name'), + action: this.options.cgiUrl, + inputs: data + } + }); + + $(tmpl).appendTo($(iframeSelector)).submit(); + }, + + /** + * Add credit card fields to post data for gateway + * @param data + * @param ccfields + * @private + */ + _preparePaymentData: function(data, ccfields) { + if (this.element.find('[data-container="' + this.options.gateway + '-cc-cvv"]').length) { + data[ccfields.cccvv] = this.element.find( + '[data-container="' + this.options.gateway + '-cc-cvv"]' + ).val(); + } + var preparedata = this._prepareExpDate(); + data[ccfields.ccexpdate] = preparedata.month + this.options.dateDelim + preparedata.year; + data[ccfields.ccnum] = this.element.find( + '[data-container="' + this.options.gateway + '-cc-number"]' + ).val(); + return data; + }, + + /** + * Grab Month and Year into one + * @returns {object} + * @private + */ + _prepareExpDate: function() { + var year = this.element.find('[data-container="' + this.options.gateway + '-cc-year"]').val(), + month = parseInt( + this.element.find('[data-container="' + this.options.gateway + '-cc-month"]').val(), + 10 + ); + if (year.length > 2) { + year = year.substring(2); + } + if (month < 10) { + month = '0' + month; + } + return {month: month, year: year}; + } + }); + + return $.mage.transparent; +}); diff --git a/app/code/Magento/Persistent/Controller/Index.php b/app/code/Magento/Persistent/Controller/Index.php index 0232cecb0bc7aa8f35766424f9872f8a037dc4b9..69e283a403112f93401ab4fa6f0a81c5bad6f522 100644 --- a/app/code/Magento/Persistent/Controller/Index.php +++ b/app/code/Magento/Persistent/Controller/Index.php @@ -5,54 +5,69 @@ */ namespace Magento\Persistent\Controller; +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\Action\Context; +use Magento\Persistent\Model\QuoteManager; +use Magento\Checkout\Model\Session as CheckoutSession; +use Magento\Customer\Model\Session as CustomerSession; +use Magento\Persistent\Helper\Session as SessionHelper; + /** * Persistent front controller */ -class Index extends \Magento\Framework\App\Action\Action +class Index extends Action { /** - * Whether clear checkout session when logout + * Persistent observer * - * @var bool + * @var \Magento\Persistent\Model\Observer */ - protected $_clearCheckoutSession = true; + protected $quoteManager; + + /** + * Checkout session + * + * @var \Magento\Checkout\Model\Session + */ + protected $checkoutSession; /** * Customer session * * @var \Magento\Customer\Model\Session */ - protected $_customerSession; + protected $customerSession; /** - * Checkout session - * - * @var \Magento\Checkout\Model\Session + * @var \Magento\Persistent\Helper\Session */ - protected $_checkoutSession; + protected $sessionHelper; /** - * Persistent observer + * Whether clear checkout session when logout * - * @var \Magento\Persistent\Model\Observer + * @var bool */ - protected $quoteManager; + protected $clearCheckoutSession = true; /** * @param \Magento\Framework\App\Action\Context $context * @param \Magento\Persistent\Model\QuoteManager $quoteManager * @param \Magento\Checkout\Model\Session $checkoutSession * @param \Magento\Customer\Model\Session $customerSession + * @param \Magento\Persistent\Helper\Session $sessionHelper */ public function __construct( - \Magento\Framework\App\Action\Context $context, - \Magento\Persistent\Model\QuoteManager $quoteManager, - \Magento\Checkout\Model\Session $checkoutSession, - \Magento\Customer\Model\Session $customerSession + Context $context, + QuoteManager $quoteManager, + CheckoutSession $checkoutSession, + CustomerSession $customerSession, + SessionHelper $sessionHelper ) { $this->quoteManager = $quoteManager; - $this->_checkoutSession = $checkoutSession; - $this->_customerSession = $customerSession; + $this->checkoutSession = $checkoutSession; + $this->customerSession = $customerSession; + $this->sessionHelper = $sessionHelper; parent::__construct($context); } @@ -64,17 +79,7 @@ class Index extends \Magento\Framework\App\Action\Action */ public function setClearCheckoutSession($clear = true) { - $this->_clearCheckoutSession = $clear; + $this->clearCheckoutSession = $clear; return $this; } - - /** - * Retrieve 'persistent session' helper instance - * - * @return \Magento\Persistent\Helper\Session - */ - protected function _getHelper() - { - return $this->_objectManager->get('Magento\Persistent\Helper\Session'); - } } diff --git a/app/code/Magento/Persistent/Controller/Index/ExpressCheckout.php b/app/code/Magento/Persistent/Controller/Index/ExpressCheckout.php index cf0a4884841bf1d38405b47b019e63d3f1ee9795..4a53814bbccb1cae33124197c448fd30b7214a30 100644 --- a/app/code/Magento/Persistent/Controller/Index/ExpressCheckout.php +++ b/app/code/Magento/Persistent/Controller/Index/ExpressCheckout.php @@ -1,21 +1,26 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Persistent\Controller\Index; -class ExpressCheckout extends \Magento\Persistent\Controller\Index +use Magento\Persistent\Controller\Index; +use Magento\Framework\Controller\ResultFactory; + +class ExpressCheckout extends Index { /** * Add appropriate session message and redirect to shopping cart * - * @return void + * @return \Magento\Framework\Controller\Result\Redirect */ public function execute() { $this->messageManager->addNotice(__('Your shopping cart has been updated with new prices.')); - $this->_redirect('checkout/cart'); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setPath('checkout/cart'); + return $resultRedirect; } } diff --git a/app/code/Magento/Persistent/Controller/Index/SaveMethod.php b/app/code/Magento/Persistent/Controller/Index/SaveMethod.php index d64059a510e3ae66ec5f16348bbe0f0ba49c76c1..64e32cb94724642e429b84d55d61c742e6f0e619 100644 --- a/app/code/Magento/Persistent/Controller/Index/SaveMethod.php +++ b/app/code/Magento/Persistent/Controller/Index/SaveMethod.php @@ -1,35 +1,33 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Persistent\Controller\Index; -class SaveMethod extends \Magento\Persistent\Controller\Index -{ - /** - * @var \Magento\Persistent\Model\QuoteManager - */ - protected $quoteManager; +use Magento\Persistent\Controller\Index; +use Magento\Framework\Controller\ResultFactory; +class SaveMethod extends Index +{ /** * Save onepage checkout method to be register * - * @return void + * @return \Magento\Framework\Controller\Result\Redirect */ public function execute() { - if ($this->_getHelper()->isPersistent()) { - $this->_getHelper()->getSession()->removePersistentCookie(); - if (!$this->_customerSession->isLoggedIn()) { - $this->_customerSession->setCustomerId(null)->setCustomerGroupId(null); + if ($this->sessionHelper->isPersistent()) { + $this->sessionHelper->getSession()->removePersistentCookie(); + if (!$this->customerSession->isLoggedIn()) { + $this->customerSession->setCustomerId(null)->setCustomerGroupId(null); } - $this->quoteManager->setGuest(); } - $checkoutUrl = $this->_redirect->getRefererUrl(); - $this->getResponse()->setRedirect($checkoutUrl . (strpos($checkoutUrl, '?') ? '&' : '?') . 'register'); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setUrl($checkoutUrl . (strpos($checkoutUrl, '?') ? '&' : '?') . 'register'); + return $resultRedirect; } } diff --git a/app/code/Magento/Persistent/Controller/Index/UnsetCookie.php b/app/code/Magento/Persistent/Controller/Index/UnsetCookie.php index 8f358bc672a0edff0b6857a99b18eb2adfef0b0f..369c63f7de88093d062f2625bab0558d86f4ad15 100644 --- a/app/code/Magento/Persistent/Controller/Index/UnsetCookie.php +++ b/app/code/Magento/Persistent/Controller/Index/UnsetCookie.php @@ -1,40 +1,44 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Persistent\Controller\Index; -class UnsetCookie extends \Magento\Persistent\Controller\Index +use Magento\Persistent\Controller\Index; +use Magento\Framework\Controller\ResultFactory; + +class UnsetCookie extends Index { /** - * Revert all persistent data + * Unset persistent cookie action * - * @return $this + * @return \Magento\Framework\Controller\Result\Redirect */ - protected function _cleanup() + public function execute() { - $this->_eventManager->dispatch('persistent_session_expired'); - $this->_customerSession->setCustomerId(null)->setCustomerGroupId(null); - if ($this->_clearCheckoutSession) { - $this->_checkoutSession->clearStorage(); + if ($this->sessionHelper->isPersistent()) { + $this->cleanup(); } - $this->_getHelper()->getSession()->removePersistentCookie(); - return $this; + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setPath('customer/account/login'); + return $resultRedirect; } /** - * Unset persistent cookie action + * Revert all persistent data * - * @return void + * @return $this */ - public function execute() + protected function cleanup() { - if ($this->_getHelper()->isPersistent()) { - $this->_cleanup(); + $this->_eventManager->dispatch('persistent_session_expired'); + $this->customerSession->setCustomerId(null)->setCustomerGroupId(null); + if ($this->clearCheckoutSession) { + $this->checkoutSession->clearStorage(); } - $this->_redirect('customer/account/login'); - return; + $this->sessionHelper->getSession()->removePersistentCookie(); + return $this; } } diff --git a/app/code/Magento/Persistent/composer.json b/app/code/Magento/Persistent/composer.json index 6b71977bb0d02f8105c6b0fc6ab5b57c6345fd7b..820efe841ed01b4dac02fff0edadcc44590e78b1 100644 --- a/app/code/Magento/Persistent/composer.json +++ b/app/code/Magento/Persistent/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-cron": "0.74.0-beta6", - "magento/module-page-cache": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-cron": "0.74.0-beta7", + "magento/module-page-cache": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ProductAlert/composer.json b/app/code/Magento/ProductAlert/composer.json index f6482671da0a929b537d916d2d9960bcf2b24161..662db83f95e273020c4aa550da04fdf71bf8bb06 100644 --- a/app/code/Magento/ProductAlert/composer.json +++ b/app/code/Magento/ProductAlert/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Quote/Model/PaymentMethodManagement.php b/app/code/Magento/Quote/Model/PaymentMethodManagement.php index fa4add6be7b7ec66b9872c55d1f1f1983ea1c475..b3a512ae1b9330585b778670e4bd647a556e4210 100644 --- a/app/code/Magento/Quote/Model/PaymentMethodManagement.php +++ b/app/code/Magento/Quote/Model/PaymentMethodManagement.php @@ -7,10 +7,13 @@ namespace Magento\Quote\Model; use Magento\Framework\Exception\State\InvalidTransitionException; +/** + * Class PaymentMethodManagement + */ class PaymentMethodManagement implements \Magento\Quote\Api\PaymentMethodManagementInterface { /** - * @var \Magento\Quote\Model\QuoteRepository + * @var \Magento\Quote\Api\CartRepositoryInterface */ protected $quoteRepository; @@ -25,12 +28,14 @@ class PaymentMethodManagement implements \Magento\Quote\Api\PaymentMethodManagem protected $methodList; /** - * @param QuoteRepository $quoteRepository + * Constructor + * + * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository * @param \Magento\Payment\Model\Checks\ZeroTotal $zeroTotalValidator * @param \Magento\Payment\Model\MethodList $methodList */ public function __construct( - \Magento\Quote\Model\QuoteRepository $quoteRepository, + \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, \Magento\Payment\Model\Checks\ZeroTotal $zeroTotalValidator, \Magento\Payment\Model\MethodList $methodList ) { @@ -45,7 +50,7 @@ class PaymentMethodManagement implements \Magento\Quote\Api\PaymentMethodManagem public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method) { /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->quoteRepository->getActive($cartId); + $quote = $this->quoteRepository->get($cartId); $method->setChecks([ \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT, @@ -87,7 +92,7 @@ class PaymentMethodManagement implements \Magento\Quote\Api\PaymentMethodManagem public function get($cartId) { /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->quoteRepository->getActive($cartId); + $quote = $this->quoteRepository->get($cartId); $payment = $quote->getPayment(); if (!$payment->getId()) { return null; @@ -101,7 +106,7 @@ class PaymentMethodManagement implements \Magento\Quote\Api\PaymentMethodManagem public function getList($cartId) { /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->quoteRepository->getActive($cartId); + $quote = $this->quoteRepository->get($cartId); return $this->methodList->getAvailableMethods($quote); } } diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 88010642002f69ba6d36ff56c882fd2f96076ccd..377ba1d34f937857dc446288129b6cb389284e1d 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -11,6 +11,7 @@ namespace Magento\Quote\Model; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Api\Data\GroupInterface; use Magento\Framework\Model\AbstractExtensibleModel; +use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Model\Quote\Address; use Magento\Sales\Model\Resource; use Magento\Sales\Model\Status; @@ -1857,10 +1858,12 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C } /** - * @param \Magento\Quote\Model\Quote\Payment $payment + * Adds a payment to quote + * + * @param PaymentInterface $payment * @return $this */ - public function addPayment(\Magento\Quote\Model\Quote\Payment $payment) + public function addPayment(PaymentInterface $payment) { $payment->setQuote($this); if (!$payment->getId()) { @@ -1870,10 +1873,12 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C } /** - * @param \Magento\Quote\Model\Quote\Payment $payment - * @return \Magento\Quote\Model\Quote\Payment + * Sets payment to current quote + * + * @param PaymentInterface $payment + * @return PaymentInterface */ - public function setPayment(\Magento\Quote\Model\Quote\Payment $payment) + public function setPayment(PaymentInterface $payment) { if (!$this->getIsMultiPayment() && ($old = $this->getPayment())) { $payment->setId($old->getId()); diff --git a/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php b/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php index 9e34d40fdb342ab5ede3cd784d687250c89c41fe..a65e71d224697d8d38abad335a3ba3354482a6c4 100644 --- a/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php +++ b/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php @@ -67,11 +67,9 @@ class ToOrderPayment '\Magento\Sales\Api\Data\OrderPaymentInterface' ); $orderPayment->setAdditionalInformation( - serialize( - array_merge( - $object->getAdditionalInformation(), - [Substitution::INFO_KEY_TITLE => $object->getMethodInstance()->getTitle()] - ) + array_merge( + $object->getAdditionalInformation(), + [Substitution::INFO_KEY_TITLE => $object->getMethodInstance()->getTitle()] ) ); // set directly on the model diff --git a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php index 70dd9e5238ad2e7427574c95c5f39ed533dea5a4..78751a96441cc1cf17f18f01eb3d41fe2fc2f252 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php @@ -34,12 +34,20 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->quoteRepositoryMock = $this->getMock('\Magento\Quote\Model\QuoteRepository', [], [], '', false); - $this->methodListMock = $this->getMock('\Magento\Payment\Model\MethodList', [], [], '', false); - $this->zeroTotalMock = $this->getMock('\Magento\Payment\Model\Checks\ZeroTotal', [], [], '', false); + $this->quoteRepositoryMock = $this->getMockForAbstractClass( + 'Magento\Quote\Api\CartRepositoryInterface', + [], + '', + false, + true, + true, + [] + ); + $this->methodListMock = $this->getMock('Magento\Payment\Model\MethodList', [], [], '', false); + $this->zeroTotalMock = $this->getMock('Magento\Payment\Model\Checks\ZeroTotal', [], [], '', false); $this->model = $this->objectManager->getObject( - '\Magento\Quote\Model\PaymentMethodManagement', + 'Magento\Quote\Model\PaymentMethodManagement', [ 'quoteRepository' => $this->quoteRepositoryMock, 'methodList' => $this->methodListMock, @@ -51,13 +59,13 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase public function testGetPaymentIfPaymentMethodNotSet() { $cartId = 11; - $quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false); - $paymentMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', [], [], '', false); + $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false); + $paymentMock = $this->getMock('Magento\Quote\Model\Quote\Payment', [], [], '', false); $quoteMock->expects($this->once())->method('getPayment')->will($this->returnValue($paymentMock)); $paymentMock->expects($this->once())->method('getId')->will($this->returnValue(null)); $this->quoteRepositoryMock->expects($this->once()) - ->method('getActive') + ->method('get') ->with($cartId) ->will($this->returnValue($quoteMock)); @@ -68,14 +76,14 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase { $cartId = 11; - $paymentMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', [], [], '', false); + $paymentMock = $this->getMock('Magento\Quote\Model\Quote\Payment', [], [], '', false); $paymentMock->expects($this->once())->method('getId')->will($this->returnValue(1)); - $quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false); + $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false); $quoteMock->expects($this->once())->method('getPayment')->will($this->returnValue($paymentMock)); $this->quoteRepositoryMock->expects($this->once()) - ->method('getActive') + ->method('get') ->with($cartId) ->will($this->returnValue($quoteMock)); $this->assertEquals($paymentMock, $this->model->get($cartId)); @@ -84,13 +92,13 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase public function testGetList() { $cartId = 10; - $quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false); + $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false); $this->quoteRepositoryMock->expects($this->once()) - ->method('getActive') + ->method('get') ->with($cartId) ->will($this->returnValue($quoteMock)); - $paymentMethod = $this->getMock('\Magento\Quote\Api\Data\PaymentMethodInterface'); + $paymentMethod = $this->getMock('Magento\Quote\Api\Data\PaymentMethodInterface'); $this->methodListMock->expects($this->once()) ->method('getAvailableMethods') ->with($quoteMock) @@ -106,15 +114,15 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $paymentMethod = 'checkmo'; $quoteMock = $this->getMock( - '\Magento\Quote\Model\Quote', + 'Magento\Quote\Model\Quote', ['setTotalsCollectedFlag', 'getPayment', 'isVirtual', 'getBillingAddress', 'collectTotals', 'save'], [], '', false ); - $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with($cartId)->willReturn($quoteMock); + $this->quoteRepositoryMock->expects($this->once())->method('get')->with($cartId)->willReturn($quoteMock); - $methodMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); + $methodMock = $this->getMock('Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); $methodMock->expects($this->once()) ->method('setChecks') ->with([ @@ -127,7 +135,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $methodMock->expects($this->once())->method('getData')->willReturn($methodData); $paymentMock = $this->getMock( - '\Magento\Quote\Model\Quote\Payment', + 'Magento\Quote\Model\Quote\Payment', ['importData', 'getMethod', 'getMethodInstance', 'getId'], [], '', @@ -137,7 +145,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $paymentMock->expects($this->once())->method('getMethod')->willReturn($paymentMethod); $billingAddressMock = $this->getMock( - '\Magento\Quote\Model\Quote\Address', + 'Magento\Quote\Model\Quote\Address', ['getCountryId', 'setPaymentMethod'], [], '', @@ -153,7 +161,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(true); $quoteMock->expects($this->exactly(2))->method('getBillingAddress')->willReturn($billingAddressMock); - $methodInstance = $this->getMock('\Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); + $methodInstance = $this->getMock('Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); $this->zeroTotalMock->expects($this->once()) @@ -179,15 +187,15 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $methodData = ['method' => 'data']; $quoteMock = $this->getMock( - '\Magento\Quote\Model\Quote', + 'Magento\Quote\Model\Quote', ['getPayment', 'isVirtual', 'getBillingAddress'], [], '', false ); - $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with($cartId)->willReturn($quoteMock); + $this->quoteRepositoryMock->expects($this->once())->method('get')->with($cartId)->willReturn($quoteMock); - $methodMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); + $methodMock = $this->getMock('Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); $methodMock->expects($this->once()) ->method('setChecks') ->with([ @@ -199,10 +207,10 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase ->willReturnSelf(); $methodMock->expects($this->once())->method('getData')->willReturn($methodData); - $paymentMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', ['importData', 'getMethod'], [], '', false); + $paymentMock = $this->getMock('Magento\Quote\Model\Quote\Payment', ['importData', 'getMethod'], [], '', false); $paymentMock->expects($this->once())->method('importData')->with($methodData)->willReturnSelf(); - $billingAddressMock = $this->getMock('\Magento\Quote\Model\Quote\Address', ['getCountryId'], [], '', false); + $billingAddressMock = $this->getMock('Magento\Quote\Model\Quote\Address', ['getCountryId'], [], '', false); $billingAddressMock->expects($this->once())->method('getCountryId')->willReturn(null); $quoteMock->expects($this->once())->method('getPayment')->willReturn($paymentMock); @@ -223,15 +231,15 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $paymentMethod = 'checkmo'; $quoteMock = $this->getMock( - '\Magento\Quote\Model\Quote', + 'Magento\Quote\Model\Quote', ['getPayment', 'isVirtual', 'getBillingAddress'], [], '', false ); - $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with($cartId)->willReturn($quoteMock); + $this->quoteRepositoryMock->expects($this->once())->method('get')->with($cartId)->willReturn($quoteMock); - $methodMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); + $methodMock = $this->getMock('Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); $methodMock->expects($this->once()) ->method('setChecks') ->with([ @@ -244,7 +252,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $methodMock->expects($this->once())->method('getData')->willReturn($methodData); $paymentMock = $this->getMock( - '\Magento\Quote\Model\Quote\Payment', + 'Magento\Quote\Model\Quote\Payment', ['importData', 'getMethod', 'getMethodInstance'], [], '', @@ -254,7 +262,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $paymentMock->expects($this->once())->method('getMethod')->willReturn($paymentMethod); $billingAddressMock = $this->getMock( - '\Magento\Quote\Model\Quote\Address', + 'Magento\Quote\Model\Quote\Address', ['getCountryId', 'setPaymentMethod'], [], '', @@ -270,7 +278,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(true); $quoteMock->expects($this->exactly(2))->method('getBillingAddress')->willReturn($billingAddressMock); - $methodInstance = $this->getMock('\Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); + $methodInstance = $this->getMock('Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); $this->zeroTotalMock->expects($this->once()) @@ -288,15 +296,15 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $paymentMethod = 'checkmo'; $quoteMock = $this->getMock( - '\Magento\Quote\Model\Quote', + 'Magento\Quote\Model\Quote', ['getPayment', 'isVirtual', 'getShippingAddress', 'setTotalsCollectedFlag', 'collectTotals', 'save'], [], '', false ); - $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with($cartId)->willReturn($quoteMock); + $this->quoteRepositoryMock->expects($this->once())->method('get')->with($cartId)->willReturn($quoteMock); - $methodMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); + $methodMock = $this->getMock('Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); $methodMock->expects($this->once()) ->method('setChecks') ->with([ @@ -309,7 +317,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $methodMock->expects($this->once())->method('getData')->willReturn($methodData); $paymentMock = $this->getMock( - '\Magento\Quote\Model\Quote\Payment', + 'Magento\Quote\Model\Quote\Payment', ['importData', 'getMethod', 'getMethodInstance', 'getId'], [], '', @@ -319,7 +327,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $paymentMock->expects($this->once())->method('getMethod')->willReturn($paymentMethod); $shippingAddressMock = $this->getMock( - '\Magento\Quote\Model\Quote\Address', + 'Magento\Quote\Model\Quote\Address', ['getCountryId', 'setPaymentMethod'], [], '', @@ -335,7 +343,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(false); $quoteMock->expects($this->exactly(4))->method('getShippingAddress')->willReturn($shippingAddressMock); - $methodInstance = $this->getMock('\Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); + $methodInstance = $this->getMock('Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); $this->zeroTotalMock->expects($this->once()) @@ -361,15 +369,15 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $methodData = ['method' => 'data']; $quoteMock = $this->getMock( - '\Magento\Quote\Model\Quote', + 'Magento\Quote\Model\Quote', ['getPayment', 'isVirtual', 'getShippingAddress'], [], '', false ); - $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with($cartId)->willReturn($quoteMock); + $this->quoteRepositoryMock->expects($this->once())->method('get')->with($cartId)->willReturn($quoteMock); - $methodMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); + $methodMock = $this->getMock('Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); $methodMock->expects($this->once()) ->method('setChecks') ->with([ @@ -381,10 +389,10 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase ->willReturnSelf(); $methodMock->expects($this->once())->method('getData')->willReturn($methodData); - $paymentMock = $this->getMock('\Magento\Quote\Model\Quote\Payment', ['importData'], [], '', false); + $paymentMock = $this->getMock('Magento\Quote\Model\Quote\Payment', ['importData'], [], '', false); $paymentMock->expects($this->once())->method('importData')->with($methodData)->willReturnSelf(); - $shippingAddressMock = $this->getMock('\Magento\Quote\Model\Quote\Address', ['getCountryId'], [], '', false); + $shippingAddressMock = $this->getMock('Magento\Quote\Model\Quote\Address', ['getCountryId'], [], '', false); $shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(null); $quoteMock->expects($this->once())->method('getPayment')->willReturn($paymentMock); diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php index b68aeb602acb6cfd7d7d8af9cf45b60595dcd6c6..aa6099192147fe2557b93e465f822f1b30753d57 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php @@ -113,7 +113,7 @@ class ToOrderPaymentTest extends \PHPUnit_Framework_TestCase ); $orderPayment->expects($this->once()) ->method('setAdditionalInformation') - ->with(serialize(array_merge($additionalInfo, [Substitution::INFO_KEY_TITLE => $paymentMethodTitle]))) + ->with(array_merge($additionalInfo, [Substitution::INFO_KEY_TITLE => $paymentMethodTitle])) ->willReturnSelf(); $orderPayment->expects($this->once()) ->method('setCcNumber') diff --git a/app/code/Magento/Quote/composer.json b/app/code/Magento/Quote/composer.json index c4bf2a50e6d26dbf3884fd47edee836d756ea200..1e9c6075223d256f7c0446991c4c26096cff6261 100644 --- a/app/code/Magento/Quote/composer.json +++ b/app/code/Magento/Quote/composer.json @@ -3,25 +3,25 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-catalog-rule": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-authorization": "0.74.0-beta6", - "magento/module-payment": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-sales-sequence": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-catalog-rule": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-authorization": "0.74.0-beta7", + "magento/module-payment": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-sales-sequence": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml index 4eeb1ff2b61a7e865d24c28af7411c599b7c3f05..0b46fc59fb7dcbead0e93d40563787ce7f6af5b7 100644 --- a/app/code/Magento/Quote/etc/di.xml +++ b/app/code/Magento/Quote/etc/di.xml @@ -25,7 +25,6 @@ <preference for="Magento\Quote\Api\Data\TotalsInterface" type="\Magento\Quote\Model\Cart\Totals" /> <preference for="Magento\Quote\Api\Data\TotalsItemInterface" type="\Magento\Quote\Model\Quote\Cart\Totals\Item" /> <preference for="Magento\Quote\Api\Data\CurrencyInterface" type="\Magento\Quote\Model\Cart\Currency" /> - <preference for="Magento\Quote\Api\GuestCartManagementInterface" type="Magento\Quote\Model\GuestCart\GuestCartManagement" /> <preference for="Magento\Quote\Api\GuestCartRepositoryInterface" type="Magento\Quote\Model\GuestCart\GuestCartRepository" /> <preference for="Magento\Quote\Api\GuestCartItemRepositoryInterface" type="Magento\Quote\Model\GuestCart\GuestCartItemRepository" /> @@ -35,7 +34,6 @@ <preference for="Magento\Quote\Api\GuestShippingAddressManagementInterface" type="Magento\Quote\Model\GuestCart\GuestShippingAddressManagement" /> <preference for="Magento\Quote\Api\GuestShippingMethodManagementInterface" type="Magento\Quote\Model\GuestCart\GuestShippingMethodManagement" /> <preference for="Magento\Quote\Api\GuestBillingAddressManagementInterface" type="Magento\Quote\Model\GuestCart\GuestBillingAddressManagement" /> - <type name="Magento\Webapi\Controller\Rest\ParamsOverrider"> <arguments> <argument name="paramOverriders" xsi:type="array"> @@ -43,4 +41,14 @@ </argument> </arguments> </type> + <type name="Magento\Quote\Model\QuoteRepository"> + <arguments> + <argument name="quoteCollection" xsi:type="object">Magento\Quote\Model\Resource\Quote\Collection\Proxy</argument> + </arguments> + </type> + <type name="Magento\Quote\Model\Quote\Address"> + <arguments> + <argument name="addressConfig" xsi:type="object">Magento\Customer\Model\Address\Config\Proxy</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Reports/composer.json b/app/code/Magento/Reports/composer.json index 575834f57dafa4f07f7bb71ab6935fde724e4731..da54b6503db78f7a07f41f55682f196bc169e91a 100644 --- a/app/code/Magento/Reports/composer.json +++ b/app/code/Magento/Reports/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-log": "0.74.0-beta6", - "magento/module-wishlist": "0.74.0-beta6", - "magento/module-review": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-downloadable": "0.74.0-beta6", - "magento/module-sales-rule": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-log": "0.74.0-beta7", + "magento/module-wishlist": "0.74.0-beta7", + "magento/module-review": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-downloadable": "0.74.0-beta7", + "magento/module-sales-rule": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/RequireJs/composer.json b/app/code/Magento/RequireJs/composer.json index 968f8b00f4780f6abfd675c4d73350b3d1b10f95..09b0a38dcb6ef123f32e19d05b29590d0a1679c1 100644 --- a/app/code/Magento/RequireJs/composer.json +++ b/app/code/Magento/RequireJs/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Review/Block/Form.php b/app/code/Magento/Review/Block/Form.php index 9682f444c4100126155f6daa0ecde88b656ce156..cf506a09857d50ca75e60af14307933802b9678b 100644 --- a/app/code/Magento/Review/Block/Form.php +++ b/app/code/Magento/Review/Block/Form.php @@ -163,7 +163,11 @@ class Form extends \Magento\Framework\View\Element\Template */ public function getProductInfo() { - return $this->productRepository->getById($this->getProductId()); + return $this->productRepository->getById( + $this->getProductId(), + false, + $this->_storeManager->getStore()->getId() + ); } /** diff --git a/app/code/Magento/Review/Model/Resource/Review/Collection.php b/app/code/Magento/Review/Model/Resource/Review/Collection.php index 7bd2de244b7adb3bdff739d5782cb681e832c41b..d32a6b04ac03043b9fc8a2c596ece7d84af58eaf 100644 --- a/app/code/Magento/Review/Model/Resource/Review/Collection.php +++ b/app/code/Magento/Review/Model/Resource/Review/Collection.php @@ -17,35 +17,35 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac * * @var string */ - protected $_reviewTable; + protected $_reviewTable = null; /** * Review detail table * * @var string */ - protected $_reviewDetailTable; + protected $_reviewDetailTable = null; /** * Review status table * * @var string */ - protected $_reviewStatusTable; + protected $_reviewStatusTable = null; /** * Review entity table * * @var string */ - protected $_reviewEntityTable; + protected $_reviewEntityTable = null; /** * Review store table * * @var string */ - protected $_reviewStoreTable; + protected $_reviewStoreTable = null; /** * Add store data flag @@ -111,11 +111,6 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac protected function _construct() { $this->_init('Magento\Review\Model\Review', 'Magento\Review\Model\Resource\Review'); - $this->_reviewTable = $this->getTable('review'); - $this->_reviewDetailTable = $this->getTable('review_detail'); - $this->_reviewStatusTable = $this->getTable('review_status'); - $this->_reviewEntityTable = $this->getTable('review_entity'); - $this->_reviewStoreTable = $this->getTable('review_store'); } /** @@ -127,7 +122,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac { parent::_initSelect(); $this->getSelect()->join( - ['detail' => $this->_reviewDetailTable], + ['detail' => $this->getReviewDetailTable()], 'main_table.review_id = detail.review_id', ['detail_id', 'title', 'detail', 'nickname', 'customer_id'] ); @@ -156,7 +151,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac { $inCond = $this->getConnection()->prepareSqlCondition('store.store_id', ['in' => $storeId]); $this->getSelect()->join( - ['store' => $this->_reviewStoreTable], + ['store' => $this->getReviewStoreTable()], 'main_table.review_id=store.review_id', [] ); @@ -184,18 +179,19 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac */ public function addEntityFilter($entity, $pkValue) { + $reviewEntityTable = $this->getReviewEntityTable(); if (is_numeric($entity)) { $this->addFilter('entity', $this->getConnection()->quoteInto('main_table.entity_id=?', $entity), 'string'); } elseif (is_string($entity)) { $this->_select->join( - $this->_reviewEntityTable, - 'main_table.entity_id=' . $this->_reviewEntityTable . '.entity_id', + $reviewEntityTable, + 'main_table.entity_id=' . $reviewEntityTable . '.entity_id', ['entity_code'] ); $this->addFilter( 'entity', - $this->getConnection()->quoteInto($this->_reviewEntityTable . '.entity_code=?', $entity), + $this->getConnection()->quoteInto($reviewEntityTable . '.entity_code=?', $entity), 'string' ); } @@ -268,7 +264,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac public function addReviewsTotalCount() { $this->_select->joinLeft( - ['r' => $this->_reviewTable], + ['r' => $this->getReviewTable()], 'main_table.entity_pk_value = r.entity_pk_value', ['total_reviews' => new \Zend_Db_Expr('COUNT(r.review_id)')] )->group( @@ -311,7 +307,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac $storesToReviews = []; if (count($reviewsIds) > 0) { $inCond = $adapter->prepareSqlCondition('review_id', ['in' => $reviewsIds]); - $select = $adapter->select()->from($this->_reviewStoreTable)->where($inCond); + $select = $adapter->select()->from($this->getReviewStoreTable())->where($inCond); $result = $adapter->fetchAll($select); foreach ($result as $row) { if (!isset($storesToReviews[$row['review_id']])) { @@ -329,4 +325,69 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac } } } + + /** + * Get review table + * + * @return string + */ + protected function getReviewTable() + { + if ($this->_reviewTable === null) { + $this->_reviewTable = $this->getTable('review'); + } + return $this->_reviewTable; + } + + /** + * Get review detail table + * + * @return string + */ + protected function getReviewDetailTable() + { + if ($this->_reviewDetailTable === null) { + $this->_reviewDetailTable = $this->getTable('review_detail'); + } + return $this->_reviewDetailTable; + } + + /** + * Get review status table + * + * @return string + */ + protected function getReviewStatusTable() + { + if ($this->_reviewStatusTable === null) { + $this->_reviewStatusTable = $this->getTable('review_status'); + } + return $this->_reviewStatusTable; + } + + /** + * Get review entity table + * + * @return string + */ + protected function getReviewEntityTable() + { + if ($this->_reviewEntityTable === null) { + $this->_reviewEntityTable = $this->getTable('review_entity'); + } + return $this->_reviewEntityTable; + } + + /** + * Get review store table + * + * @return string + */ + protected function getReviewStoreTable() + { + if ($this->_reviewStoreTable === null) { + $this->_reviewStoreTable = $this->getTable('review_store'); + } + return $this->_reviewStoreTable; + } } diff --git a/app/code/Magento/Review/Test/Unit/Block/FormTest.php b/app/code/Magento/Review/Test/Unit/Block/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..32a59cf8334c59766d49955916821c587a1bb32f --- /dev/null +++ b/app/code/Magento/Review/Test/Unit/Block/FormTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Review\Test\Unit\Block; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class FormTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Review\Block\Form */ + protected $object; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** + * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $requestMock; + + /** @var \Magento\Framework\View\Element\Template\Context|\PHPUnit_Framework_MockObject_MockObject */ + protected $context; + + /** + * @var \Magento\Review\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $reviewDataMock; + + /** @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $productRepository; + + /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $storeManager; + + protected function setUp() + { + $this->storeManager = $this->getMock('\Magento\Store\Model\StoreManagerInterface'); + $this->requestMock = $this->getMock('\Magento\Framework\App\RequestInterface'); + $this->reviewDataMock = $this->getMockBuilder('\Magento\Review\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + + $this->reviewDataMock->expects($this->once()) + ->method('getIsGuestAllowToWrite') + ->willReturn(true); + + $this->context = $this->getMock('Magento\Framework\View\Element\Template\Context', [], [], '', false); + $this->context->expects( + $this->any() + )->method( + 'getStoreManager' + )->will( + $this->returnValue($this->storeManager) + ); + $this->context->expects($this->any()) + ->method('getRequest') + ->willReturn($this->requestMock); + $this->productRepository = $this->getMock('\Magento\Catalog\Api\ProductRepositoryInterface'); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->object = $this->objectManagerHelper->getObject( + 'Magento\Review\Block\Form', + [ + 'context' => $this->context, + 'reviewData' => $this->reviewDataMock, + 'productRepository' => $this->productRepository, + ] + ); + } + + public function testGetProductInfo() + { + $productId = 3; + $storeId = 1; + + $this->storeManager->expects( + $this->any() + )->method( + 'getStore' + )->will( + $this->returnValue(new \Magento\Framework\Object(['id' => $storeId])) + ); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('id', false) + ->willReturn($productId); + + $productMock = $this->getMock('Magento\Catalog\Api\Data\ProductInterface'); + $this->productRepository->expects($this->once()) + ->method('getById') + ->with($productId, false, $storeId) + ->willReturn($productMock); + + $this->assertSame($productMock, $this->object->getProductInfo()); + } +} diff --git a/app/code/Magento/Review/Test/Unit/Model/Resource/Review/CollectionTest.php b/app/code/Magento/Review/Test/Unit/Model/Resource/Review/CollectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..67e67cdf8381745aa356f7b85129945f2d563d33 --- /dev/null +++ b/app/code/Magento/Review/Test/Unit/Model/Resource/Review/CollectionTest.php @@ -0,0 +1,188 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Review\Test\Unit\Model\Resource\Review; + +class CollectionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Review\Model\Resource\Review\Collection + */ + protected $model; + + /** + * @var \Zend_Db_Select | \PHPUnit_Framework_MockObject_MockObject + */ + protected $selectMock; + + /** + * @var \Magento\Store\Model\StoreManagerInterface | \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var \Magento\Framework\Model\Resource\Db\AbstractDb | \PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Zend_Db_Adapter_Abstract | \PHPUnit_Framework_MockObject_MockObject + */ + protected $readerAdapterMock; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + + public function setUp() + { + $store = $this->getMock('\Magento\Store\Model\Store', ['getId'], [], '', false); + $store->expects($this->any())->method('getId')->will($this->returnValue(1)); + $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($store)); + $this->objectManager = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this)); + $this->resourceMock = $this->getMockBuilder('Magento\Framework\Model\Resource\Db\AbstractDb') + ->disableOriginalConstructor() + ->setMethods(['getReadConnection', 'getMainTable', 'getTable']) + ->getMockForAbstractClass(); + $this->readerAdapterMock = $this->getMockBuilder('\Zend_Db_Adapter_Abstract') + ->disableOriginalConstructor() + ->setMethods(['select', 'prepareSqlCondition', 'quoteInto']) + ->getMockForAbstractClass(); + $this->selectMock = $this->getMockBuilder('\Zend_Db_Select') + ->disableOriginalConstructor() + ->getMock(); + $this->readerAdapterMock->expects($this->any()) + ->method('select') + ->willReturn($this->selectMock); + $this->resourceMock->expects($this->any()) + ->method('getReadConnection') + ->willReturn($this->readerAdapterMock); + $this->resourceMock->expects($this->any()) + ->method('getMainTable') + ->willReturn('maintable'); + $this->resourceMock->expects($this->any()) + ->method('getTable') + ->willReturnCallback(function ($table) { + return $table; + }); + $this->model = $this->objectManager->getObject( + '\Magento\Review\Model\Resource\Review\Collection', + [ + 'storeManager' => $this->storeManagerMock, + 'resource' => $this->resourceMock, + ] + ); + + } + + public function testInitSelect() + { + $this->selectMock->expects($this->once()) + ->method('join') + ->with( + ['detail' => 'review_detail'], + 'main_table.review_id = detail.review_id', + ['detail_id', 'title', 'detail', 'nickname', 'customer_id'] + ); + $this->objectManager->getObject( + '\Magento\Review\Model\Resource\Review\Collection', + [ + 'storeManager' => $this->storeManagerMock, + 'resource' => $this->resourceMock, + ] + ); + } + + public function testAddStoreFilter() + { + $this->readerAdapterMock->expects($this->once()) + ->method('prepareSqlCondition'); + $this->selectMock->expects($this->once()) + ->method('join') + ->with( + ['store' => 'review_store'], + 'main_table.review_id=store.review_id', + [] + ); + $this->model->addStoreFilter(1); + } + + /** + * @param int|string $entity + * @param int $pkValue + * @param string $quoteIntoArguments1 + * @param string $quoteIntoArguments2 + * @param string $quoteIntoReturn1 + * @param string $quoteIntoReturn2 + * @param int $callNum + * @dataProvider addEntityFilterDataProvider + */ + public function testAddEntityFilter( + $entity, + $pkValue, + $quoteIntoArguments1, + $quoteIntoArguments2, + $quoteIntoReturn1, + $quoteIntoReturn2, + $callNum + ) { + $this->readerAdapterMock->expects($this->at(0)) + ->method('quoteInto') + ->with($quoteIntoArguments1[0], $quoteIntoArguments1[1]) + ->willReturn($quoteIntoReturn1); + $this->readerAdapterMock->expects($this->at(1)) + ->method('quoteInto') + ->with($quoteIntoArguments2[0], $quoteIntoArguments2[1]) + ->willReturn($quoteIntoReturn2); + $this->selectMock->expects($this->exactly($callNum)) + ->method('join') + ->with( + 'review_entity', + 'main_table.entity_id=' . 'review_entity' . '.entity_id', + ['entity_code'] + ); + $this->model->addEntityFilter($entity, $pkValue); + } + + public function addEntityFilterDataProvider() + { + return [ + [ + 1, + 2, + ['main_table.entity_id=?', 1], + ['main_table.entity_pk_value=?', 2], + 'quoteIntoReturn1', + 'quoteIntoReturn2', + 0 + ], + [ + 'entity', + 2, + ['review_entity.entity_code=?', 'entity'], + ['main_table.entity_pk_value=?', 2], + 'quoteIntoReturn1', + 'quoteIntoReturn2', + 1 + ] + ]; + } + + public function testAddReviewsTotalCount() + { + $this->selectMock->expects($this->once()) + ->method('joinLeft') + ->with( + ['r' => 'review'], + 'main_table.entity_pk_value = r.entity_pk_value', + ['total_reviews' => new \Zend_Db_Expr('COUNT(r.review_id)')] + )->willReturnSelf(); + $this->selectMock->expects($this->once()) + ->method('group'); + $this->model->addReviewsTotalCount(); + } +} diff --git a/app/code/Magento/Review/composer.json b/app/code/Magento/Review/composer.json index 35197e270227acf8a04a3e0915411c076af46e0d..10b89c9f5b04bff6ba97ad1d1c720a0970314673 100644 --- a/app/code/Magento/Review/composer.json +++ b/app/code/Magento/Review/composer.json @@ -3,22 +3,22 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-newsletter": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-ui": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-newsletter": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-ui": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta6" + "magento/module-cookie": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Review/view/adminhtml/layout/customer_form.xml b/app/code/Magento/Review/view/adminhtml/layout/customer_index_edit.xml similarity index 91% rename from app/code/Magento/Review/view/adminhtml/layout/customer_form.xml rename to app/code/Magento/Review/view/adminhtml/layout/customer_index_edit.xml index 09fe7121ca4f6407351238f0802a4fd999dd1e35..a6fe4a094eb0f1425af6a7dcf876f619ce58d1c1 100644 --- a/app/code/Magento/Review/view/adminhtml/layout/customer_form.xml +++ b/app/code/Magento/Review/view/adminhtml/layout/customer_index_edit.xml @@ -7,7 +7,7 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> - <referenceBlock name="form"> + <referenceBlock name="customer_form"> <block acl="Magento_Review::reviews_all" class="Magento\Review\Block\Adminhtml\ReviewTab" name="reviews" /> </referenceBlock> </body> diff --git a/app/code/Magento/Rss/composer.json b/app/code/Magento/Rss/composer.json index cb02900c44ef080abe82adcc3879c5394cf4640c..2e3f52bd9644d567c605deb87d855e01c32f6e8c 100644 --- a/app/code/Magento/Rss/composer.json +++ b/app/code/Magento/Rss/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Rule/composer.json b/app/code/Magento/Rule/composer.json index 4e9e4fd3965676ec789fcae5df2f3fc27a1601ca..f03b63cba961c0adf432192ca5b2809a5a134c6e 100644 --- a/app/code/Magento/Rule/composer.json +++ b/app/code/Magento/Rule/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php b/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php index 28afae3c0f9528343770c22dfe283b82324a7c5a..3a4a5c23033f48a2b2fcc41eb519330cb3e955fd 100644 --- a/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php @@ -57,6 +57,14 @@ interface CreditmemoCommentInterface extends \Magento\Framework\Api\ExtensibleDa */ public function getCreatedAt(); + /** + * Sets the credit memo created-at timestamp. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the credit memo ID. * diff --git a/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php b/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php index 205d5c37b3f1033132c9679a240e036223a2e5e8..ce5a46b9838b447159bcf96b87bbd8753e46ed5e 100644 --- a/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php +++ b/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php @@ -383,6 +383,15 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter * @return string Credit memo created-at timestamp. */ public function getCreatedAt(); + + /** + * Sets the credit memo created-at timestamp. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the credit memo status. * diff --git a/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php index 10c86a870231cd4cd0c24a165c1cc5cf022bcdaf..ec6fce4016f6a0d397858b3ebf5848cacdc3e047 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php @@ -55,6 +55,14 @@ interface InvoiceCommentInterface extends \Magento\Framework\Api\ExtensibleDataI */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the invoice. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the ID for the invoice. * diff --git a/app/code/Magento/Sales/Api/Data/InvoiceInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceInterface.php index e17decc98e0bbd364313f43a2d7373cbfd7990cc..fcbe20b83f28c96b939277d524a04dec9f923b7d 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceInterface.php @@ -319,6 +319,14 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the invoice. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the discount amount for the invoice. * diff --git a/app/code/Magento/Sales/Api/Data/OrderInterface.php b/app/code/Magento/Sales/Api/Data/OrderInterface.php index 7bd62fbe1c3228b2241690b981a7f0ab8c2f84eb..42ccf6aee23c151088f27b7d6e714237a75ce845 100644 --- a/app/code/Magento/Sales/Api/Data/OrderInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderInterface.php @@ -914,6 +914,14 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the order. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the customer date-of-birth (DOB) for the order. * diff --git a/app/code/Magento/Sales/Api/Data/OrderItemInterface.php b/app/code/Magento/Sales/Api/Data/OrderItemInterface.php index 6e59b03a98370feb88a6d6522c9fb84560e12bf3..e10e196380670f54fd11963a281738c50226d20c 100644 --- a/app/code/Magento/Sales/Api/Data/OrderItemInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderItemInterface.php @@ -578,6 +578,14 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the order item. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the description for the order item. * diff --git a/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php b/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php index 4ef7daf322d37f0ca1b26f0ab7501e7ad5a79fcf..3a27e326c3b88866c1cb03ec4c84227391e46416 100644 --- a/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php @@ -64,6 +64,14 @@ interface OrderStatusHistoryInterface extends \Magento\Framework\Api\ExtensibleD */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the order status history. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the ID for the order status history. * diff --git a/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php index 213b7c2e5e4931bd9f9295aee3b537f817891a68..e6bcd71928463f0bd09446f60bc303a1a31f4864 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php @@ -55,6 +55,14 @@ interface ShipmentCommentInterface extends \Magento\Framework\Api\ExtensibleData */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the shipment comment. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the ID for the shipment comment. * diff --git a/app/code/Magento/Sales/Api/Data/ShipmentInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentInterface.php index 41c676ea2081219e35d7e7d6561206f4f5bf5c24..67b3b60b05266ef8febff35e6df0952414ebdea1 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentInterface.php @@ -103,6 +103,14 @@ interface ShipmentInterface extends \Magento\Framework\Api\ExtensibleDataInterfa */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the shipment. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the customer ID for the shipment. * diff --git a/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php index 7ace1ead4114db6c8c81c9a3921d56f1e9195727..e9bfa3915c4074096f9d5023e5a5c13514a92267 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php @@ -76,6 +76,14 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the shipment package. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets the description for the shipment package. * diff --git a/app/code/Magento/Sales/Api/Data/TransactionInterface.php b/app/code/Magento/Sales/Api/Data/TransactionInterface.php index 224d9765582f0e3381846f159814103e72111351..92d431c6e0b5754ed8222c5deb9f8fb02f28ce05 100644 --- a/app/code/Magento/Sales/Api/Data/TransactionInterface.php +++ b/app/code/Magento/Sales/Api/Data/TransactionInterface.php @@ -75,6 +75,14 @@ interface TransactionInterface extends \Magento\Framework\Api\ExtensibleDataInte */ public function getTransactionId(); + /** + * Sets the transaction ID for the transaction. + * + * @param int $id + * @return $this + */ + public function setTransactionId($id); + /** * Gets the parent ID for the transaction. * @@ -138,6 +146,14 @@ interface TransactionInterface extends \Magento\Framework\Api\ExtensibleDataInte */ public function getCreatedAt(); + /** + * Sets the created-at timestamp for the transaction. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + /** * Gets an array of child transactions for the transaction. * diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php index 6dd4434c6e0ef0fc6c47735fa50d84c312ee3230..ea065d8eea7a6dc695f3c1d2c023e39af251f1a6 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php @@ -60,7 +60,7 @@ class View extends \Magento\Backend\Block\Template $this->addChild( 'submit_button', 'Magento\Backend\Block\Widget\Button', - ['id' => 'submit_comment_button', 'label' => __('Submit Comment'), 'class' => 'save'] + ['id' => 'submit_comment_button', 'label' => __('Submit Comment'), 'class' => 'action-secondary save'] ); return parent::_prepareLayout(); } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Store.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Store.php index 908dabf48c15cc5f7e4cdaec3eec7c08431fd7a3..cf83b3bc125c7ffd8cb391fd3ea55b687629ab5a 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Store.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Store.php @@ -30,6 +30,6 @@ class Store extends \Magento\Sales\Block\Adminhtml\Order\Create\AbstractCreate */ public function getHeaderText() { - return __('Please select a store.'); + return __('Please select a store'); } } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php index ad82046b66ed50ea6914ed6775cb90e8b482661e..d0284f3175fdc79c07fd9938f5634fa76cab7ef9 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php @@ -54,7 +54,7 @@ class History extends \Magento\Backend\Block\Template $button = $this->getLayout()->createBlock( 'Magento\Backend\Block\Widget\Button' )->setData( - ['label' => __('Submit Comment'), 'class' => 'save', 'onclick' => $onclick] + ['label' => __('Submit Comment'), 'class' => 'action-save action-secondary', 'onclick' => $onclick] ); $this->setChild('submit_button', $button); return parent::_prepareLayout(); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/EditInterface.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/EditInterface.php deleted file mode 100644 index 79fefe2a18515d4f143f561aba1c9a2f9e3f4cde..0000000000000000000000000000000000000000 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/EditInterface.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php -/** - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Sales\Controller\Adminhtml\Order; - -interface EditInterface extends \Magento\Framework\App\ActionInterface -{ -} diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 94847e91dbe200c9ea34764d4981d08ac986db98..43f4b95497720ed8df3e7f74a4cc03e31255b980 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -35,7 +35,6 @@ use Magento\Sales\Model\Resource\Order\Status\History\Collection as HistoryColle * @method \Magento\Sales\Model\Resource\Order getResource() * @method int getGiftMessageId() * @method \Magento\Sales\Model\Order setGiftMessageId(int $value) - * @method \Magento\Sales\Model\Order setCreatedAt(string $value) * @method bool hasBillingAddressId() * @method \Magento\Sales\Model\Order unsBillingAddressId() * @method bool hasShippingAddressId() @@ -920,6 +919,8 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * Order state setter. * If status is specified, will add order status history with specified comment * the setData() cannot be overridden because of compatibility issues with resource model + * By default allows to set any state. Can also update status to default or specified value + * Complete and closed states are encapsulated intentionally * * @param string $state * @param string|bool $status @@ -927,6 +928,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param bool $isCustomerNotified * @param bool $shouldProtectState * @return \Magento\Sales\Model\Order + * @throws \Magento\Framework\Exception\LocalizedException */ public function setState( $state, @@ -935,29 +937,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface $isCustomerNotified = null, $shouldProtectState = true ) { - return $this->_setState($state, $status, $comment, $isCustomerNotified, $shouldProtectState); - } - /** - * Order state protected setter. - * By default allows to set any state. Can also update status to default or specified value - * Complete and closed states are encapsulated intentionally, see the _checkState() - * - * @param string $state - * @param string|bool $status - * @param string $comment - * @param bool $isCustomerNotified - * @param bool $shouldProtectState - * @return $this - * @throws \Magento\Framework\Exception\LocalizedException - */ - protected function _setState( - $state, - $status = false, - $comment = '', - $isCustomerNotified = null, - $shouldProtectState = false - ) { // attempt to set the specified state if ($shouldProtectState) { if ($this->isStateProtected($state)) { @@ -966,17 +946,32 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface ); } } - $this->setData('state', $state); + + $transport = new \Magento\Framework\Object( + [ + 'state' => $state, + 'status' => $status, + 'comment' => $comment, + 'is_customer_notified' => $isCustomerNotified + ] + ); + + $this->_eventManager->dispatch( + 'sales_order_state_change_before', + ['order' => $this, 'transport' => $transport] + ); + $status = $transport->getStatus(); + $this->setData('state', $transport->getState()); // add status history if ($status) { if ($status === true) { - $status = $this->getConfig()->getStateDefaultStatus($state); + $status = $this->getConfig()->getStateDefaultStatus($transport->getState()); } $this->setStatus($status); - $history = $this->addStatusHistoryComment($comment, false); + $history = $this->addStatusHistoryComment($transport->getComment(), false); // no sense to set $status again - $history->setIsCustomerNotified($isCustomerNotified); + $history->setIsCustomerNotified($transport->getIsCustomerNotified()); } return $this; } @@ -1167,7 +1162,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface $this->setTotalCanceled($this->getGrandTotal() - $this->getTotalPaid()); $this->setBaseTotalCanceled($this->getBaseGrandTotal() - $this->getBaseTotalPaid()); - $this->_setState($cancelState, true, $comment); + $this->setState($cancelState, true, $comment, null, false); } elseif (!$graceful) { throw new \Magento\Framework\Exception\LocalizedException(__('We cannot cancel this order.')); } @@ -2485,6 +2480,14 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface return $this->getData(OrderInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(OrderInterface::CREATED_AT, $createdAt); + } + /** * Returns customer_dob * diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Order/Creditmemo.php index 9e77f5afd8635e1b6421a1915684a4c0a858cbd0..7fbc58d77171b57ccf708e81a9a4ad77a827293b 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo.php @@ -20,7 +20,6 @@ use Magento\Sales\Model\EntityInterface; * * @method \Magento\Sales\Model\Resource\Order\Creditmemo _getResource() * @method \Magento\Sales\Model\Resource\Order\Creditmemo getResource() - * @method \Magento\Sales\Model\Order\Creditmemo setCreatedAt(string $value) * @method \Magento\Sales\Model\Order\Invoice setSendEmail(bool $value) * @method \Magento\Sales\Model\Order\Invoice setCustomerNote(string $value) * @method string getCustomerNote() @@ -1034,6 +1033,14 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt return $this->getData(CreditmemoInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(CreditmemoInterface::CREATED_AT, $createdAt); + } + /** * Returns creditmemo_status * diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php index a488162c322611e892d33bc90cd60be5dac7cc6f..2dac94c26b818bc2eab23acc83aea3079166a9d5 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php @@ -12,7 +12,6 @@ use Magento\Sales\Model\AbstractModel; /** * @method \Magento\Sales\Model\Resource\Order\Creditmemo\Comment _getResource() * @method \Magento\Sales\Model\Resource\Order\Creditmemo\Comment getResource() - * @method \Magento\Sales\Model\Order\Creditmemo\Comment setCreatedAt(string $value) */ class Comment extends AbstractModel implements CreditmemoCommentInterface { @@ -126,6 +125,14 @@ class Comment extends AbstractModel implements CreditmemoCommentInterface return $this->getData(CreditmemoCommentInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(CreditmemoCommentInterface::CREATED_AT, $createdAt); + } + /** * Returns is_customer_notified * diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoCommentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoCommentSender.php index 2d6598ec9a830a7f0ca18a53e3291ce1446bb368..09d01d2e0a55cdf874ba8cbe9add9567998a5c5c 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoCommentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoCommentSender.php @@ -11,6 +11,7 @@ use Magento\Sales\Model\Order\Email\Container\CreditmemoCommentIdentity; use Magento\Sales\Model\Order\Email\Container\Template; use Magento\Sales\Model\Order\Email\NotifySender; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class CreditmemoCommentSender @@ -22,22 +23,32 @@ class CreditmemoCommentSender extends NotifySender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param CreditmemoCommentIdentity $identityContainer * @param Order\Email\SenderBuilderFactory $senderBuilderFactory * @param \Psr\Log\LoggerInterface $logger * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, CreditmemoCommentIdentity $identityContainer, \Magento\Sales\Model\Order\Email\SenderBuilderFactory $senderBuilderFactory, \Psr\Log\LoggerInterface $logger, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -57,18 +68,28 @@ class CreditmemoCommentSender extends NotifySender $formattedShippingAddress = ''; } $formattedBillingAddress = $this->addressRenderer->format($order->getBillingAddress(), 'html'); - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'creditmemo' => $creditmemo, - 'comment' => $comment, - 'billing' => $order->getBillingAddress(), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $formattedShippingAddress, - 'formattedBillingAddress' => $formattedBillingAddress, + + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'creditmemo' => $creditmemo, + 'comment' => $comment, + 'billing' => $order->getBillingAddress(), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $formattedShippingAddress, + 'formattedBillingAddress' => $formattedBillingAddress, + ] ] ); + $this->eventManager->dispatch( + 'email_creditmemo_comment_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + return $this->checkAndSend($order, $notify); } } diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php index e476e5ec8b544272154e907ce04cf46be2dd08ba..8bcd58fafd941a3dc185de14ac7f33b932ed2d7b 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/CreditmemoSender.php @@ -13,6 +13,7 @@ use Magento\Sales\Model\Order\Email\Container\Template; use Magento\Sales\Model\Order\Email\Sender; use Magento\Sales\Model\Resource\Order\Creditmemo as CreditmemoResource; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class CreditmemoSender @@ -43,6 +44,13 @@ class CreditmemoSender extends Sender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param CreditmemoIdentity $identityContainer @@ -52,6 +60,7 @@ class CreditmemoSender extends Sender * @param CreditmemoResource $creditmemoResource * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, @@ -61,13 +70,15 @@ class CreditmemoSender extends Sender PaymentHelper $paymentHelper, CreditmemoResource $creditmemoResource, \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->paymentHelper = $paymentHelper; $this->creditmemoResource = $creditmemoResource; $this->globalConfig = $globalConfig; $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -100,24 +111,32 @@ class CreditmemoSender extends Sender $formattedBillingAddress = $this->addressRenderer->format($order->getBillingAddress(), 'html'); - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'creditmemo' => $creditmemo, - 'comment' => $creditmemo->getCustomerNoteNotify() ? $creditmemo->getCustomerNote() : '', - 'billing' => $order->getBillingAddress(), - 'payment_html' => $this->getPaymentHtml($order), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $formattedShippingAddress, - 'formattedBillingAddress' => $formattedBillingAddress, + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'creditmemo' => $creditmemo, + 'comment' => $creditmemo->getCustomerNoteNotify() + ? $creditmemo->getCustomerNote() : '', + 'billing' => $order->getBillingAddress(), + 'payment_html' => $this->getPaymentHtml($order), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $formattedShippingAddress, + 'formattedBillingAddress' => $formattedBillingAddress + ] ] ); + $this->eventManager->dispatch( + 'email_creditmemo_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + if ($this->checkAndSend($order)) { $creditmemo->setEmailSent(true); - $this->creditmemoResource->saveAttribute($creditmemo, ['send_email', 'email_sent']); - return true; } } diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceCommentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceCommentSender.php index 75529455b3f5baa8b0e5e089465de1b48e6fc2eb..b994034cf480a12c17738832e1bb44e9920be569 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceCommentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceCommentSender.php @@ -11,6 +11,7 @@ use Magento\Sales\Model\Order\Email\Container\Template; use Magento\Sales\Model\Order\Email\NotifySender; use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class InvoiceCommentSender @@ -22,22 +23,32 @@ class InvoiceCommentSender extends NotifySender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param InvoiceCommentIdentity $identityContainer * @param Order\Email\SenderBuilderFactory $senderBuilderFactory * @param \Psr\Log\LoggerInterface $logger * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, InvoiceCommentIdentity $identityContainer, \Magento\Sales\Model\Order\Email\SenderBuilderFactory $senderBuilderFactory, \Psr\Log\LoggerInterface $logger, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -57,17 +68,28 @@ class InvoiceCommentSender extends NotifySender $formattedShippingAddress = ''; } $formattedBillingAddress = $this->addressRenderer->format($order->getBillingAddress(), 'html'); - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'invoice' => $invoice, - 'comment' => $comment, - 'billing' => $order->getBillingAddress(), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $formattedShippingAddress, - 'formattedBillingAddress' => $formattedBillingAddress, + + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'invoice' => $invoice, + 'comment' => $comment, + 'billing' => $order->getBillingAddress(), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $formattedShippingAddress, + 'formattedBillingAddress' => $formattedBillingAddress, + ] ] ); + + $this->eventManager->dispatch( + 'email_invoice_comment_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + return $this->checkAndSend($order, $notify); } } diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php index 0796ff0443b198be2f4f2533e825fb8eca25c2f9..d879b0f529aab42479a89acc597f14867f4268a4 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php @@ -13,6 +13,7 @@ use Magento\Sales\Model\Order\Email\Sender; use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Resource\Order\Invoice as InvoiceResource; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class InvoiceSender @@ -43,6 +44,13 @@ class InvoiceSender extends Sender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param InvoiceIdentity $identityContainer @@ -52,6 +60,7 @@ class InvoiceSender extends Sender * @param InvoiceResource $invoiceResource * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, @@ -61,13 +70,15 @@ class InvoiceSender extends Sender PaymentHelper $paymentHelper, InvoiceResource $invoiceResource, \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->paymentHelper = $paymentHelper; $this->invoiceResource = $invoiceResource; $this->globalConfig = $globalConfig; $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -98,25 +109,33 @@ class InvoiceSender extends Sender $formattedShippingAddress = ''; } $formattedBillingAddress = $this->addressRenderer->format($order->getBillingAddress(), 'html'); - - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'invoice' => $invoice, - 'comment' => $invoice->getCustomerNoteNotify() ? $invoice->getCustomerNote() : '', - 'billing' => $order->getBillingAddress(), - 'payment_html' => $this->getPaymentHtml($order), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $formattedShippingAddress, - 'formattedBillingAddress' => $formattedBillingAddress + + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'invoice' => $invoice, + 'comment' => $invoice->getCustomerNoteNotify() ? $invoice->getCustomerNote() + : '', + 'billing' => $order->getBillingAddress(), + 'payment_html' => $this->getPaymentHtml($order), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $formattedShippingAddress, + 'formattedBillingAddress' => $formattedBillingAddress + ] ] ); + $this->eventManager->dispatch( + 'email_invoice_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + if ($this->checkAndSend($order)) { $invoice->setEmailSent(true); - $this->invoiceResource->saveAttribute($invoice, ['send_email', 'email_sent']); - return true; } } diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/OrderCommentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/OrderCommentSender.php index 10abfd138dcc392e9e953ef613214bf28949bdb5..64f67cb80ce8f98b8fc07de60fc5a48efeae534e 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/OrderCommentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/OrderCommentSender.php @@ -10,6 +10,7 @@ use Magento\Sales\Model\Order\Email\Container\OrderCommentIdentity; use Magento\Sales\Model\Order\Email\Container\Template; use Magento\Sales\Model\Order\Email\NotifySender; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class OrderCommentSender @@ -21,22 +22,32 @@ class OrderCommentSender extends NotifySender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param OrderCommentIdentity $identityContainer * @param Order\Email\SenderBuilderFactory $senderBuilderFactory * @param \Psr\Log\LoggerInterface $logger * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, OrderCommentIdentity $identityContainer, \Magento\Sales\Model\Order\Email\SenderBuilderFactory $senderBuilderFactory, \Psr\Log\LoggerInterface $logger, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -55,16 +66,27 @@ class OrderCommentSender extends NotifySender $formattedShippingAddress = ''; } $formattedBillingAddress = $this->addressRenderer->format($order->getBillingAddress(), 'html'); - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'comment' => $comment, - 'billing' => $order->getBillingAddress(), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $formattedShippingAddress, - 'formattedBillingAddress' => $formattedBillingAddress, + + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'comment' => $comment, + 'billing' => $order->getBillingAddress(), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $formattedShippingAddress, + 'formattedBillingAddress' => $formattedBillingAddress, + ] ] ); + + $this->eventManager->dispatch( + 'email_order_comment_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + return $this->checkAndSend($order, $notify); } } diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/OrderSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/OrderSender.php index dc2d544d335bd35b9aa5c81327f272bb2c927872..59c7e404c940a55abd252ae429a572e0d8b45c66 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/OrderSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/OrderSender.php @@ -12,9 +12,11 @@ use Magento\Sales\Model\Order\Email\Container\Template; use Magento\Sales\Model\Order\Email\Sender; use Magento\Sales\Model\Resource\Order as OrderResource; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class OrderSender + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class OrderSender extends Sender { @@ -40,6 +42,13 @@ class OrderSender extends Sender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param OrderIdentity $identityContainer @@ -49,6 +58,7 @@ class OrderSender extends Sender * @param OrderResource $orderResource * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, @@ -58,13 +68,15 @@ class OrderSender extends Sender PaymentHelper $paymentHelper, OrderResource $orderResource, \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->paymentHelper = $paymentHelper; $this->orderResource = $orderResource; $this->globalConfig = $globalConfig; $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -89,9 +101,7 @@ class OrderSender extends Sender if (!$this->globalConfig->getValue('sales_email/general/async_sending') || $forceSyncMode) { if ($this->checkAndSend($order)) { $order->setEmailSent(true); - $this->orderResource->saveAttribute($order, ['send_email', 'email_sent']); - return true; } } @@ -109,16 +119,26 @@ class OrderSender extends Sender */ protected function prepareTemplate(Order $order) { - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'billing' => $order->getBillingAddress(), - 'payment_html' => $this->getPaymentHtml($order), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $this->addressRenderer->format($order->getShippingAddress(), 'html'), - 'formattedBillingAddress' => $this->addressRenderer->format($order->getBillingAddress(), 'html'), + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'billing' => $order->getBillingAddress(), + 'payment_html' => $this->getPaymentHtml($order), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $this->addressRenderer->format($order->getShippingAddress(), 'html'), + 'formattedBillingAddress' => $this->addressRenderer->format($order->getBillingAddress(), 'html'), + ] ] ); + + $this->eventManager->dispatch( + 'email_order_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + parent::prepareTemplate($order); } diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentCommentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentCommentSender.php index 1173cc951fe6455e4ddd0829d6a31e2274b6c7ca..d3555b8240b9a27934f0bbc6144d64db0a2ba563 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentCommentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentCommentSender.php @@ -11,6 +11,7 @@ use Magento\Sales\Model\Order\Email\Container\Template; use Magento\Sales\Model\Order\Email\NotifySender; use Magento\Sales\Model\Order\Shipment; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class ShipmentCommentSender @@ -22,22 +23,32 @@ class ShipmentCommentSender extends NotifySender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param ShipmentCommentIdentity $identityContainer * @param Order\Email\SenderBuilderFactory $senderBuilderFactory * @param \Psr\Log\LoggerInterface $logger * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, ShipmentCommentIdentity $identityContainer, \Magento\Sales\Model\Order\Email\SenderBuilderFactory $senderBuilderFactory, \Psr\Log\LoggerInterface $logger, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -57,17 +68,28 @@ class ShipmentCommentSender extends NotifySender $formattedShippingAddress = ''; } $formattedBillingAddress = $this->addressRenderer->format($order->getBillingAddress(), 'html'); - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'shipment' => $shipment, - 'comment' => $comment, - 'billing' => $order->getBillingAddress(), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $formattedShippingAddress, - 'formattedBillingAddress' => $formattedBillingAddress, + + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'shipment' => $shipment, + 'comment' => $comment, + 'billing' => $order->getBillingAddress(), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $formattedShippingAddress, + 'formattedBillingAddress' => $formattedBillingAddress, + ] ] ); + + $this->eventManager->dispatch( + 'email_shipment_comment_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + return $this->checkAndSend($order, $notify); } } diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php index cedd82ae34d6426ed8fff4d60ff9a48565b8ca20..96a62f88588435d2695a8e97c1a466aa161d4986 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php @@ -13,10 +13,11 @@ use Magento\Sales\Model\Order\Email\Sender; use Magento\Sales\Model\Order\Shipment; use Magento\Sales\Model\Resource\Order\Shipment as ShipmentResource; use Magento\Sales\Model\Order\Address\Renderer; +use Magento\Framework\Event\ManagerInterface; /** * Class ShipmentSender - * + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShipmentSender extends Sender @@ -43,6 +44,13 @@ class ShipmentSender extends Sender */ protected $addressRenderer; + /** + * Application Event Dispatcher + * + * @var ManagerInterface + */ + protected $eventManager; + /** * @param Template $templateContainer * @param ShipmentIdentity $identityContainer @@ -52,6 +60,7 @@ class ShipmentSender extends Sender * @param ShipmentResource $shipmentResource * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig * @param Renderer $addressRenderer + * @param ManagerInterface $eventManager */ public function __construct( Template $templateContainer, @@ -61,13 +70,15 @@ class ShipmentSender extends Sender PaymentHelper $paymentHelper, ShipmentResource $shipmentResource, \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig, - Renderer $addressRenderer + Renderer $addressRenderer, + ManagerInterface $eventManager ) { parent::__construct($templateContainer, $identityContainer, $senderBuilderFactory, $logger); $this->paymentHelper = $paymentHelper; $this->shipmentResource = $shipmentResource; $this->globalConfig = $globalConfig; $this->addressRenderer = $addressRenderer; + $this->eventManager = $eventManager; } /** @@ -99,24 +110,33 @@ class ShipmentSender extends Sender } $formattedBillingAddress = $this->addressRenderer->format($order->getBillingAddress(), 'html'); - $this->templateContainer->setTemplateVars( - [ - 'order' => $order, - 'shipment' => $shipment, - 'comment' => $shipment->getCustomerNoteNotify() ? $shipment->getCustomerNote() : '', - 'billing' => $order->getBillingAddress(), - 'payment_html' => $this->getPaymentHtml($order), - 'store' => $order->getStore(), - 'formattedShippingAddress' => $formattedShippingAddress, - 'formattedBillingAddress' => $formattedBillingAddress + $transport = new \Magento\Framework\Object( + ['template_vars' => + [ + 'order' => $order, + 'shipment' => $shipment, + 'comment' => $shipment->getCustomerNoteNotify() + ? $shipment->getCustomerNote() + : '', + 'billing' => $order->getBillingAddress(), + 'payment_html' => $this->getPaymentHtml($order), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $formattedShippingAddress, + 'formattedBillingAddress' => $formattedBillingAddress + ] ] ); + $this->eventManager->dispatch( + 'email_shipment_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport->getTemplateVars()); + if ($this->checkAndSend($order)) { $shipment->setEmailSent(true); - $this->shipmentResource->saveAttribute($shipment, ['send_email', 'email_sent']); - return true; } } diff --git a/app/code/Magento/Sales/Model/Order/Invoice.php b/app/code/Magento/Sales/Model/Order/Invoice.php index 8317b7041d61f3e747af2b644050854b3b55174d..036aec685121162933181a05e6c66af57af6d58c 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice.php +++ b/app/code/Magento/Sales/Model/Order/Invoice.php @@ -11,7 +11,6 @@ use Magento\Sales\Model\AbstractModel; use Magento\Sales\Model\EntityInterface; /** - * @method \Magento\Sales\Model\Order\Invoice setCreatedAt(string $value) * @method \Magento\Sales\Model\Order\Invoice setSendEmail(bool $value) * @method \Magento\Sales\Model\Order\Invoice setCustomerNote(string $value) * @method string getCustomerNote() @@ -969,6 +968,14 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface return $this->getData(InvoiceInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(InvoiceInterface::CREATED_AT, $createdAt); + } + /** * Returns discount_amount * diff --git a/app/code/Magento/Sales/Model/Order/Invoice/Comment.php b/app/code/Magento/Sales/Model/Order/Invoice/Comment.php index 074e77b3638e656906f3da22e3727cea61423e98..e7b99dea1593ed699d4f76e6f745256f780e8075 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice/Comment.php +++ b/app/code/Magento/Sales/Model/Order/Invoice/Comment.php @@ -12,7 +12,6 @@ use Magento\Sales\Model\AbstractModel; /** * @method \Magento\Sales\Model\Resource\Order\Invoice\Comment _getResource() * @method \Magento\Sales\Model\Resource\Order\Invoice\Comment getResource() - * @method \Magento\Sales\Model\Order\Invoice\Comment setCreatedAt(string $value) */ class Comment extends AbstractModel implements InvoiceCommentInterface { @@ -126,6 +125,14 @@ class Comment extends AbstractModel implements InvoiceCommentInterface return $this->getData(InvoiceCommentInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(InvoiceCommentInterface::CREATED_AT, $createdAt); + } + /** * Returns is_customer_notified * diff --git a/app/code/Magento/Sales/Model/Order/Item.php b/app/code/Magento/Sales/Model/Order/Item.php index b23a34296c690d5584dc2a6e314401669981bd3a..602cde0a32e3ccbbc03195aa4933e4fdb81b3079 100644 --- a/app/code/Magento/Sales/Model/Order/Item.php +++ b/app/code/Magento/Sales/Model/Order/Item.php @@ -14,7 +14,6 @@ use Magento\Sales\Api\Data\OrderItemInterface; * * @method \Magento\Sales\Model\Resource\Order\Item _getResource() * @method \Magento\Sales\Model\Resource\Order\Item getResource() - * @method \Magento\Sales\Model\Order\Item setCreatedAt(string $value) * @method int getGiftMessageId() * @method \Magento\Sales\Model\Order\Item setGiftMessageId(int $value) * @method int getGiftMessageAvailable() @@ -949,6 +948,14 @@ class Item extends AbstractModel implements OrderItemInterface return $this->getData(OrderItemInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(OrderItemInterface::CREATED_AT, $createdAt); + } + /** * Returns description * diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php index 3c0d281f3e27cd8630d0471e6e8f505c29f6b10c..16cc9b45365adec1da8225d0c7ef6cd27ba813f1 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php @@ -19,7 +19,6 @@ use Magento\Sales\Model\AbstractModel; * * @method \Magento\Sales\Model\Resource\Order\Payment\Transaction _getResource() * @method \Magento\Sales\Model\Resource\Order\Payment\Transaction getResource() - * @method \Magento\Sales\Model\Order\Payment\Transaction setCreatedAt(string $value) * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) @@ -922,6 +921,14 @@ class Transaction extends AbstractModel implements TransactionInterface return $this->getData(TransactionInterface::TRANSACTION_ID); } + /** + * {@inheritdoc} + */ + public function setTransactionId($id) + { + return $this->setData(TransactionInterface::TRANSACTION_ID, $id); + } + /** * Returns method * @@ -1002,8 +1009,9 @@ class Transaction extends AbstractModel implements TransactionInterface return $this->getData(TransactionInterface::IS_CLOSED); } + //@codeCoverageIgnoreStart /** - * Returns created_at + * Gets the created-at timestamp for the transaction. * * @return string */ @@ -1012,7 +1020,14 @@ class Transaction extends AbstractModel implements TransactionInterface return $this->getData(TransactionInterface::CREATED_AT); } - //@codeCoverageIgnoreStart + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(TransactionInterface::CREATED_AT, $createdAt); + } + /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Shipment.php b/app/code/Magento/Sales/Model/Order/Shipment.php index 3472e9663ad337ceb64c7399b06a60e389883708..6763a4895dfe30891530cdeb2c25a61e47047c14 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment.php +++ b/app/code/Magento/Sales/Model/Order/Shipment.php @@ -15,7 +15,6 @@ use Magento\Sales\Model\EntityInterface; * * @method \Magento\Sales\Model\Resource\Order\Shipment _getResource() * @method \Magento\Sales\Model\Resource\Order\Shipment getResource() - * @method \Magento\Sales\Model\Order\Shipment setCreatedAt(string $value) * @method \Magento\Sales\Model\Order\Invoice setSendEmail(bool $value) * @method \Magento\Sales\Model\Order\Invoice setCustomerNote(string $value) * @method string getCustomerNote() @@ -626,6 +625,14 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa return $this->getData(ShipmentInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(ShipmentInterface::CREATED_AT, $createdAt); + } + /** * Returns customer_id * diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Comment.php b/app/code/Magento/Sales/Model/Order/Shipment/Comment.php index 43361d79d59c4a4b6e403a7b0c7677ba1dbc1784..d1e9a5ac880bce77a0cef548f077e6e09ce754e7 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Comment.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Comment.php @@ -12,7 +12,6 @@ use Magento\Sales\Model\AbstractModel; /** * @method \Magento\Sales\Model\Resource\Order\Shipment\Comment _getResource() * @method \Magento\Sales\Model\Resource\Order\Shipment\Comment getResource() - * @method \Magento\Sales\Model\Order\Shipment\Comment setCreatedAt(string $value) */ class Comment extends AbstractModel implements ShipmentCommentInterface { @@ -126,6 +125,14 @@ class Comment extends AbstractModel implements ShipmentCommentInterface return $this->getData(ShipmentCommentInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(ShipmentCommentInterface::CREATED_AT, $createdAt); + } + /** * Returns is_customer_notified * diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Track.php b/app/code/Magento/Sales/Model/Order/Shipment/Track.php index 325c9837bee51bc906c55afdc3d172c9da8966f3..f5b15181cb8fcb89a5ddb301b28a4290573010ec 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Track.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Track.php @@ -12,7 +12,6 @@ use Magento\Sales\Model\AbstractModel; /** * @method \Magento\Sales\Model\Resource\Order\Shipment\Track _getResource() * @method \Magento\Sales\Model\Resource\Order\Shipment\Track getResource() - * @method \Magento\Sales\Model\Order\Shipment\Track setCreatedAt(string $value) * * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -232,6 +231,14 @@ class Track extends AbstractModel implements ShipmentTrackInterface return $this->getData(ShipmentTrackInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(ShipmentTrackInterface::CREATED_AT, $createdAt); + } + /** * Returns description * diff --git a/app/code/Magento/Sales/Model/Order/Status/History.php b/app/code/Magento/Sales/Model/Order/Status/History.php index edd828956c8241f11fcc8d929f4618a36d75e858..b442ebba05f7df7af8691e42949e79c174b0cb74 100644 --- a/app/code/Magento/Sales/Model/Order/Status/History.php +++ b/app/code/Magento/Sales/Model/Order/Status/History.php @@ -14,7 +14,6 @@ use Magento\Sales\Model\AbstractModel; * * @method \Magento\Sales\Model\Resource\Order\Status\History _getResource() * @method \Magento\Sales\Model\Resource\Order\Status\History getResource() - * @method \Magento\Sales\Model\Order\Status\History setCreatedAt(string $value) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class History extends AbstractModel implements OrderStatusHistoryInterface @@ -196,6 +195,14 @@ class History extends AbstractModel implements OrderStatusHistoryInterface return $this->getData(OrderStatusHistoryInterface::CREATED_AT); } + /** + * {@inheritdoc} + */ + public function setCreatedAt($createdAt) + { + return $this->setData(OrderStatusHistoryInterface::CREATED_AT, $createdAt); + } + /** * Returns entity_id * diff --git a/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Email/AsyncSendingTest.php b/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Email/AsyncSendingTest.php index 69f3f6e0df310d27dc7c7c6774ad5a62ca1e82cb..9359af03ee68dfcb020c7e7ed1a9923bd4d456ec 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Email/AsyncSendingTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Email/AsyncSendingTest.php @@ -63,7 +63,7 @@ class AsyncSendingTest extends \PHPUnit_Framework_TestCase public function testAfterSave($value, $oldValue, $eventName) { $path = 'sales_email/general/async_sending'; - $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT; + $scope = \Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT; $this->object->setData(['value' => $value, 'path' => $path, 'scope' => $scope]); diff --git a/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Grid/AsyncIndexingTest.php b/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Grid/AsyncIndexingTest.php index 972cfae38e2ae4273235a2c7a7d1ac260b4f45a3..729c19940ccff8b5f464eeeb895bc74e5aeafa16 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Grid/AsyncIndexingTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Config/Backend/Grid/AsyncIndexingTest.php @@ -63,7 +63,7 @@ class AsyncIndexingTest extends \PHPUnit_Framework_TestCase public function testAfterSave($value, $oldValue, $eventName) { $path = 'dev/grid/async_indexing'; - $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT; + $scope = \Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT; $this->object->setData(['value' => $value, 'path' => $path, 'scope' => $scope]); diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/AbstractSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/AbstractSenderTest.php index cd70e51424497d16585475b55edaab6d526e7cef..63ef953d756f00967ade66140431bef520989812 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/AbstractSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/AbstractSenderTest.php @@ -62,6 +62,11 @@ abstract class AbstractSenderTest extends \PHPUnit_Framework_TestCase */ protected $addressMock; + /** + * @var \Magento\Framework\Event\Manager | \PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -128,6 +133,7 @@ abstract class AbstractSenderTest extends \PHPUnit_Framework_TestCase $this->addressRenderer = $this->getMock('Magento\Sales\Model\Order\Address\Renderer', [], [], '', false); $this->addressMock = $this->getMock('Magento\Sales\Model\Order\Address', [], [], '', false); + $this->eventManagerMock = $this->getMock('Magento\Framework\Event\Manager', [], [], '', false); $this->paymentHelper = $this->getMock('\Magento\Payment\Helper\Data', ['getInfoBlockHtml'], [], '', false); $this->paymentHelper->expects($this->any()) diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoCommentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoCommentSenderTest.php index 977ded72038ee29f205fa6981c1f534dfdae6120..fe968f3f76438091ba4fb4d99e0901c0c1d6ebc1 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoCommentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoCommentSenderTest.php @@ -45,7 +45,8 @@ class CreditmemoCommentSenderTest extends AbstractSenderTest $this->identityContainerMock, $this->senderBuilderFactoryMock, $this->loggerMock, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php index cfe7bfc22e54f51db6edc23e02859488612fd11b..c42216226dae0a6f5fe4df3b75de089ff8229532 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/CreditmemoSenderTest.php @@ -73,7 +73,8 @@ class CreditmemoSenderTest extends AbstractSenderTest $this->paymentHelper, $this->creditmemoResourceMock, $this->globalConfig, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceCommentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceCommentSenderTest.php index 30b838341b5ce16a3d733839f911ee1014c2ccfe..4670ec2824ecb03e26ba446871b1cb7e24c0c28d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceCommentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceCommentSenderTest.php @@ -61,7 +61,8 @@ class InvoiceCommentSenderTest extends AbstractSenderTest $this->identityContainerMock, $this->senderBuilderFactoryMock, $this->loggerMock, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php index 35cb0e84b6566f2e74c0f17f20d918e8a88945a9..8ca7f14f25b291edbd91de51f28540ea4a48c8db 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/InvoiceSenderTest.php @@ -73,7 +73,8 @@ class InvoiceSenderTest extends AbstractSenderTest $this->paymentHelper, $this->invoiceResourceMock, $this->globalConfig, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderCommentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderCommentSenderTest.php index 9bb5745162152cf85610abaa6cd8af1564586c7d..3b7c92d55986fb7f5435f7210c25b0d412b85e5e 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderCommentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderCommentSenderTest.php @@ -24,7 +24,8 @@ class OrderCommentSenderTest extends AbstractSenderTest $this->identityContainerMock, $this->senderBuilderFactoryMock, $this->loggerMock, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderSenderTest.php index 5350c1924f023c6055e59eec341cb024acb687ca..7de676a36f9281413f0d008e44de723d0de385f5 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/OrderSenderTest.php @@ -50,7 +50,8 @@ class OrderSenderTest extends AbstractSenderTest $this->paymentHelper, $this->orderResourceMock, $this->globalConfig, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentCommentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentCommentSenderTest.php index 0a69bb2fcf85d7eae3c0f0841ee17be8afdd1221..7351b1444b6691440f087a99ed05fdb2db6b00e8 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentCommentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentCommentSenderTest.php @@ -43,7 +43,8 @@ class ShipmentCommentSenderTest extends AbstractSenderTest $this->identityContainerMock, $this->senderBuilderFactoryMock, $this->loggerMock, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php index a13619f0423eaaa9a0f0ee3636c0c999454a0a9c..89fab376003d21eb36bf6c702785584abab2a861 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php @@ -73,7 +73,8 @@ class ShipmentSenderTest extends AbstractSenderTest $this->paymentHelper, $this->shipmentResourceMock, $this->globalConfig, - $this->addressRenderer + $this->addressRenderer, + $this->eventManagerMock ); } diff --git a/app/code/Magento/Sales/composer.json b/app/code/Magento/Sales/composer.json index 482c2576832b49f12c0e42710c10efb31c419643..d975eed1fc1cf27009dcfa90d0ed6bf5603bd535 100644 --- a/app/code/Magento/Sales/composer.json +++ b/app/code/Magento/Sales/composer.json @@ -3,35 +3,35 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-authorization": "0.74.0-beta6", - "magento/module-payment": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-sales-rule": "0.74.0-beta6", - "magento/module-sales-sequence": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-gift-message": "0.74.0-beta6", - "magento/module-reports": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-wishlist": "0.74.0-beta6", - "magento/module-email": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-ui": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-authorization": "0.74.0-beta7", + "magento/module-payment": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-sales-rule": "0.74.0-beta7", + "magento/module-sales-sequence": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-gift-message": "0.74.0-beta7", + "magento/module-reports": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-wishlist": "0.74.0-beta7", + "magento/module-email": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-ui": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sales/etc/data_object.xml b/app/code/Magento/Sales/etc/service_data_attributes.xml similarity index 78% rename from app/code/Magento/Sales/etc/data_object.xml rename to app/code/Magento/Sales/etc/service_data_attributes.xml index 8ef8080db8a29120f255cedfe0c083f45d85e5e5..1e7f320c18ed6e98b0c979d23e80e6ff48478fa4 100644 --- a/app/code/Magento/Sales/etc/data_object.xml +++ b/app/code/Magento/Sales/etc/service_data_attributes.xml @@ -5,10 +5,10 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Sales\Api\Data\OrderInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Sales\Api\Data\OrderInterface"> <attribute code="applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface[]" /> <attribute code="item_applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsItemInterface[]" /> <attribute code="converting_from_quote" type="boolean" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/customer_form.xml b/app/code/Magento/Sales/view/adminhtml/layout/customer_index_edit.xml similarity index 91% rename from app/code/Magento/Sales/view/adminhtml/layout/customer_form.xml rename to app/code/Magento/Sales/view/adminhtml/layout/customer_index_edit.xml index 971cc57cfe03cca7f828c517d5cf674bcdf42377..b5de5df96a33838f520c890d682404ba1cc4e096 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/customer_form.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/customer_index_edit.xml @@ -7,7 +7,7 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> - <referenceBlock name="form"> + <referenceBlock name="customer_form"> <block acl="Magento_Sales::actions_view" class="Magento\Sales\Block\Adminhtml\CustomerOrdersTab" name="orders" /> </referenceBlock> </body> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_new.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_new.xml index 031d2ada6a1493e0fba975ea588642a8f3a6fe8c..a4ee30150b13a4236deca813f902e2be14da5d38 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_new.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_new.xml @@ -1,33 +1,35 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> - <update handle="sales_order_item_price"/> - <body> - <referenceContainer name="content"> - <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create" name="sales_creditmemo_create"> - <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create\Form" name="form" template="order/creditmemo/create/form.phtml"> - <block class="Magento\Sales\Block\Adminhtml\Order\View\Info" name="order_info" template="order/view/info.phtml"/> - <block class="Magento\Sales\Block\Adminhtml\Order\Payment" name="order_payment"/> - <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create\Items" name="order_items" template="order/creditmemo/create/items.phtml"> - <block class="Magento\Sales\Block\Adminhtml\Items\Renderer\DefaultRenderer" as="default" template="order/creditmemo/create/items/renderer/default.phtml"/> - <block class="Magento\Sales\Block\Adminhtml\Items\Column\Qty" name="column_qty" template="items/column/qty.phtml" group="column"/> - <block class="Magento\Sales\Block\Adminhtml\Items\Column\Name" name="column_name" template="items/column/name.phtml" group="column"/> - <block class="Magento\Framework\View\Element\Text\ListText" name="order_item_extra_info"/> - <block class="Magento\Sales\Block\Adminhtml\Order\Totalbar" name="order_totalbar" template="order/totalbar.phtml"/> - <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Totals" name="creditmemo_totals" template="order/totals.phtml"> - <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create\Adjustments" name="adjustments" template="order/creditmemo/create/totals/adjustments.phtml"/> - <block class="Magento\Sales\Block\Adminhtml\Order\Totals\Tax" name="tax" template="order/totals/tax.phtml"/> - </block> - <container name="submit_before" label="Submit Before"/> - <container name="submit_after" label="Submit After"/> - </block> - </block> - </block> - </referenceContainer> - </body> -</page> +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <update handle="sales_order_item_price"/> + <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> + + <referenceContainer name="content"> + <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create" name="sales_creditmemo_create"> + <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create\Form" name="form" template="order/creditmemo/create/form.phtml"> + <block class="Magento\Sales\Block\Adminhtml\Order\View\Info" name="order_info" template="order/view/info.phtml"/> + <block class="Magento\Sales\Block\Adminhtml\Order\Payment" name="order_payment"/> + <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create\Items" name="order_items" template="order/creditmemo/create/items.phtml"> + <block class="Magento\Sales\Block\Adminhtml\Items\Renderer\DefaultRenderer" as="default" template="order/creditmemo/create/items/renderer/default.phtml"/> + <block class="Magento\Sales\Block\Adminhtml\Items\Column\Qty" name="column_qty" template="items/column/qty.phtml" group="column"/> + <block class="Magento\Sales\Block\Adminhtml\Items\Column\Name" name="column_name" template="items/column/name.phtml" group="column"/> + <block class="Magento\Framework\View\Element\Text\ListText" name="order_item_extra_info"/> + <block class="Magento\Sales\Block\Adminhtml\Order\Totalbar" name="order_totalbar" template="order/totalbar.phtml"/> + <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Totals" name="creditmemo_totals" template="order/totals.phtml"> + <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create\Adjustments" name="adjustments" template="order/creditmemo/create/totals/adjustments.phtml"/> + <block class="Magento\Sales\Block\Adminhtml\Order\Totals\Tax" name="tax" template="order/totals/tax.phtml"/> + </block> + <container name="submit_before" label="Submit Before"/> + <container name="submit_after" label="Submit After"/> + </block> + </block> + </block> + </referenceContainer> + </body> +</page> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_view.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_view.xml index 916950e7e358e286ebf34bbc762fd64024dd2074..7208039683c8dbf06f7a60bfd8db9e311aa8cfed 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_view.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_creditmemo_view.xml @@ -8,6 +8,7 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <update handle="sales_creditmemo_item_price"/> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> <referenceContainer name="content"> <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\View" name="sales_creditmemo_view"> <block class="Magento\Sales\Block\Adminhtml\Order\Creditmemo\View\Form" name="form" template="order/creditmemo/view/form.phtml"> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_new.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_new.xml index 0f922d55922bd65f188dfa6840fa8db1c78915e6..f31b37ea47d0b5cbe64c8f688ba5501e1f433e5f 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_new.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_new.xml @@ -8,6 +8,8 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <update handle="sales_order_item_price"/> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> + <referenceContainer name="content"> <block class="Magento\Sales\Block\Adminhtml\Order\Invoice\Create" name="sales_invoice_create"> <block class="Magento\Sales\Block\Adminhtml\Order\Invoice\Create\Form" name="form" template="order/invoice/create/form.phtml"> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_view.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_view.xml index 93552d0ec38418451df0cd93d847c94a81cc1b92..e22eaae5cd8f4092cd672c407b0c521c6b129b3c 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_view.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_invoice_view.xml @@ -8,6 +8,8 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <update handle="sales_invoice_item_price"/> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> + <referenceContainer name="content"> <block class="Magento\Sales\Block\Adminhtml\Order\Invoice\View" name="sales_invoice_view"> <block class="Magento\Sales\Block\Adminhtml\Order\Invoice\View\Form" name="form" template="order/invoice/view/form.phtml"> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml index cbc91390fda6cd951fa9ebf480a3cd1b40e3c2b2..36e653b728b26412248d6286a1a0c936b4e59918 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_transactions_grid_block.xml @@ -8,6 +8,8 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <update handle="sales_transactions_grid_block"/> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> + <referenceBlock name="sales.transactions.grid"> <arguments> <argument name="id" xsi:type="string">order_transactions</argument> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_view.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_view.xml index ed5a0578d7f292c37160a53a417aa5136dce7edb..19260c6cf0849dd9c89287a9291eed94c459d08a 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_view.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_view.xml @@ -15,6 +15,8 @@ </head> <update handle="sales_order_item_price"/> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> + <referenceContainer name="content"> <block class="Magento\Sales\Block\Adminhtml\Order\View" name="sales_order_edit"/> </referenceContainer> diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_view.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_view.xml index aed08edb19e608d84b4a2397972d694dd6473754..0f7144004b45285aa108bfc37999b6596e48240f 100644 --- a/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_view.xml +++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_transactions_view.xml @@ -8,6 +8,8 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <update handle="sales_transaction_child_block"/> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> + <referenceContainer name="content"> <block class="Magento\Sales\Block\Adminhtml\Transactions\Detail" name="sales_transactions.detail" template="transactions/detail.phtml"> <block class="Magento\Sales\Block\Adminhtml\Transactions\Detail\Grid" name="sales_transactions.detail.grid" as="detail_grid"/> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml b/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml index 410e44f5977e65522e61d063142f0db15a51390e..d8e8c8eda42623412337857b7d75163a62aa8027 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/items/column/name.phtml @@ -14,33 +14,38 @@ ?> <?php if ($_item = $block->getItem()): ?> - <div id="order_item_<?php echo $_item->getId() ?>_title" class="product-title"><?php echo $block->escapeHtml($_item->getName()) ?></div> - <strong><?php echo __('SKU') ?>:</strong> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($block->getSku()))); ?> - <?php if ($block->getOrderOptions()): ?> - <dl class="item-options"> - <?php foreach ($block->getOrderOptions() as $_option): ?> - <dt><?php echo $_option['label'] ?></dt> - <dd> - <?php if (isset($_option['custom_view']) && $_option['custom_view']): ?> - <?php echo $block->getCustomizedOptionValue($_option); ?> - <?php else: ?> - <?php $_option = $block->getFormattedOption($_option['value']); ?> - <?php echo $_option['value']; ?><?php if (isset($_option['remainder']) && $_option['remainder']): ?><span id="<?php echo $_dots = 'dots' . uniqid()?>"> ...</span><span id="<?php echo $_id = 'id' . uniqid()?>"><?php echo $_option['remainder'] ?></span> - <script> -require(['prototype'], function(){ + <div id="order_item_<?php echo $_item->getId() ?>_title" + class="product-title"> + <?php echo $block->escapeHtml($_item->getName()) ?> + </div> - $('<?php echo $_id ?>').hide(); - $('<?php echo $_id ?>').up().observe('mouseover', function(){$('<?php echo $_id ?>').show();}); - $('<?php echo $_id ?>').up().observe('mouseover', function(){$('<?php echo $_dots?>').hide();}); - $('<?php echo $_id ?>').up().observe('mouseout', function(){$('<?php echo $_id ?>').hide();}); - $('<?php echo $_id ?>').up().observe('mouseout', function(){$('<?php echo $_dots ?>').show();}); + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($block->getSku()))); ?> + </div> -}); -</script> - <?php endif; ?> - <?php endif; ?> - </dd> - <?php endforeach; ?> + <?php if ($block->getOrderOptions()): ?> + <dl class="item-options"> + <?php foreach ($block->getOrderOptions() as $_option): ?> + <dt><?php echo $_option['label'] ?>:</dt> + <dd> + <?php if (isset($_option['custom_view']) && $_option['custom_view']): ?> + <?php echo $block->getCustomizedOptionValue($_option); ?> + <?php else: ?> + <?php $_option = $block->getFormattedOption($_option['value']); ?> + <?php echo $_option['value']; ?><?php if (isset($_option['remainder']) && $_option['remainder']): ?><span id="<?php echo $_dots = 'dots' . uniqid()?>"> ...</span><span id="<?php echo $_id = 'id' . uniqid()?>"><?php echo $_option['remainder'] ?></span> + <script> + require(['prototype'], function() { + $('<?php echo $_id ?>').hide(); + $('<?php echo $_id ?>').up().observe('mouseover', function(){$('<?php echo $_id ?>').show();}); + $('<?php echo $_id ?>').up().observe('mouseover', function(){$('<?php echo $_dots?>').hide();}); + $('<?php echo $_id ?>').up().observe('mouseout', function(){$('<?php echo $_id ?>').hide();}); + $('<?php echo $_id ?>').up().observe('mouseout', function(){$('<?php echo $_dots ?>').show();}); + }); + </script> + <?php endif; ?> + <?php endif; ?> + </dd> + <?php endforeach; ?> </dl> <?php endif; ?> <?php echo $block->escapeHtml($_item->getDescription()) ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/items/column/qty.phtml b/app/code/Magento/Sales/view/adminhtml/templates/items/column/qty.phtml index 91e20c1f3658451d6d43cfc54f6b657c69526e2d..46b39dc3a78af52bbe12142c47d4876c312e982a 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/items/column/qty.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/items/column/qty.phtml @@ -8,34 +8,39 @@ ?> <?php if ($_item = $block->getItem()): ?> -<table cellspacing="0" class="qty-table"> +<table class="data-table qty-table"> <tr> - <td><?php echo __('Ordered') ?></td> - <td><strong><?php echo $_item->getQtyOrdered()*1 ?></strong></td> + <th><?php echo __('Ordered') ?></th> + <td><?php echo $_item->getQtyOrdered()*1 ?></td> </tr> + <?php if ((float) $_item->getQtyInvoiced()): ?> - <tr> - <td><?php echo __('Invoiced') ?></td> - <td><strong><?php echo $_item->getQtyInvoiced()*1 ?></strong></td> - </tr> + <tr> + <th><?php echo __('Invoiced') ?></th> + <td><?php echo $_item->getQtyInvoiced()*1 ?></td> + </tr> <?php endif; ?> + <?php if ((float) $_item->getQtyShipped()): ?> - <tr> - <td><?php echo __('Shipped') ?></td> - <td><strong><?php echo $_item->getQtyShipped()*1 ?></strong></td> - </tr> + <tr> + <th><?php echo __('Shipped') ?></th> + <td><?php echo $_item->getQtyShipped()*1 ?></td> + </tr> <?php endif; ?> + <?php if ((float) $_item->getQtyRefunded()): ?> - <tr> - <td><?php echo __('Refunded') ?></td> - <td><strong><?php echo $_item->getQtyRefunded()*1 ?></strong></td> - </tr> + <tr> + <th><?php echo __('Refunded') ?></th> + <td><?php echo $_item->getQtyRefunded()*1 ?></td> + </tr> <?php endif; ?> + <?php if ((float) $_item->getQtyCanceled()): ?> - <tr> - <td><?php echo __('Canceled') ?></td> - <td><strong><?php echo $_item->getQtyCanceled()*1 ?></strong></td> - </tr> + <tr> + <th><?php echo __('Canceled') ?></th> + <td><?php echo $_item->getQtyCanceled()*1 ?></td> + </tr> <?php endif; ?> + </table> <?php endif; ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml index cbe3b6f40e5b08784d20e03f978f0940d9ee0ddc..096b7098612358a568c5d5feba5022f428dfa7db 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml @@ -8,38 +8,62 @@ ?> <?php if ($_entity = $block->getEntity()): ?> -<div id="comments_block"> - <div class="field-row"> - <label class="normal" for="history_comment"><?php echo __('Comment Text') ?></label> - <textarea name="comment[comment]" rows="3" cols="5" id="history_comment"></textarea> - </div> - <div class="clearfix"> - <div class="actions"> - <?php echo $block->getChildHtml('submit_button') ?> +<div id="comments_block" class="edit-order-comments"> + <div class="order-history-block"> + <div class="admin__field field-row"> + <label class="admin__field-label" + for="history_comment"><?php echo __('Comment Text') ?></label> + <textarea name="comment[comment]" + class="admin__control-textarea" + rows="3" + cols="5" + id="history_comment"></textarea> </div> - <div class="order-history-comments-options"> - <?php if ($block->canSendCommentEmail()): ?> - <input name="comment[is_customer_notified]" type="checkbox" id="history_notify" value="1" /><label class="normal" for="history_notify"><?php echo __('Notify Customer by Email') ?></label><br /> - <?php endif; ?> - <input name="comment[is_visible_on_front]" type="checkbox" id="history_visible" value="1" /><label class="normal" for="history_visible"> <?php echo __('Visible on Frontend') ?></label> + <div class="admin__field"> + <div class="order-history-comments-options"> + <?php if ($block->canSendCommentEmail()): ?> + <div class="admin__field admin__field-option"> + <input name="comment[is_customer_notified]" + type="checkbox" + class="admin__control-checkbox" + id="history_notify" + value="1" /> + <label class="admin__field-label" + for="history_notify"><?php echo __('Notify Customer by Email') ?></label> + </div> + <?php endif; ?> + <div class="admin__field admin__field-option"> + <input name="comment[is_visible_on_front]" + type="checkbox" + id="history_visible" + class="admin__control-checkbox" + value="1" /> + <label class="admin__field-label" + for="history_visible"> <?php echo __('Visible on Frontend') ?></label> + </div> + </div> + <div class="order-history-comments-actions"> + <?php echo $block->getChildHtml('submit_button') ?> + </div> </div> </div> + <ul class="note-list"> - <?php foreach ($_entity->getCommentsCollection(true) as $_comment): ?> - <li> - <span class="note-list-date"><?php echo $block->formatDate($_comment->getCreatedAtDate(), \IntlDateFormatter::MEDIUM) ?></span> - <span class="note-list-time"><?php echo $block->formatTime($_comment->getCreatedAtDate(), \IntlDateFormatter::MEDIUM) ?></span> - <span class="note-list-customer"> - <?php echo __('Customer') ?> - <?php if ($_comment->getIsCustomerNotified()): ?> - <span class="note-list-customer-notified"><?php echo __('Notified') ?></span> - <?php else: ?> - <span class="note-list-customer-not-notified"><?php echo __('Not Notified') ?></span> - <?php endif; ?> - </span> - <div class="note-list-comment"><?php echo $block->escapeHtml($_comment->getComment(), ['b', 'br', 'strong', 'i', 'u']) ?></div> - </li> - <?php endforeach; ?> + <?php foreach ($_entity->getCommentsCollection(true) as $_comment): ?> + <li> + <span class="note-list-date"><?php echo $block->formatDate($_comment->getCreatedAtDate(), \IntlDateFormatter::MEDIUM) ?></span> + <span class="note-list-time"><?php echo $block->formatTime($_comment->getCreatedAtDate(), \IntlDateFormatter::MEDIUM) ?></span> + <span class="note-list-customer"> + <?php echo __('Customer') ?> + <?php if ($_comment->getIsCustomerNotified()): ?> + <span class="note-list-customer-notified"><?php echo __('Notified') ?></span> + <?php else: ?> + <span class="note-list-customer-not-notified"><?php echo __('Not Notified') ?></span> + <?php endif; ?> + </span> + <div class="note-list-comment"><?php echo $block->escapeHtml($_comment->getComment(), ['b', 'br', 'strong', 'i', 'u']) ?></div> + </li> + <?php endforeach; ?> </ul> </div> <script> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/abstract.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/abstract.phtml index 956ca1eedf569a14dca9e099c7ca15f98e6e6eb2..4364258410ba46e1083242b1ac611ba6f053734b 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/abstract.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/abstract.phtml @@ -8,8 +8,8 @@ ?> -<div class="admin__fieldset-wrapper-title"> - <strong><?php echo $block->getHeaderText() ?></strong> +<div class="admin__page-section-title"> + <span class="title"><?php echo $block->getHeaderText() ?></span> <?php if($block->getButtonsHtml()): ?> <div class="actions"><?php echo $block->getButtonsHtml() ?></div> <?php endif; ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml index d166ab4edac32983b6d5f784ede2228b21e362c1..7ba8e8a79394a26020ad406ff7b7ca287cb53b4a 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/data.phtml @@ -14,82 +14,76 @@ }); </script> <div class="order-details<?php if ($block->getCustomerId()): ?> order-details-existing-customer<?php endif; ?>"> - <div class="order-details-inner"> - <div id="order-additional_area" style="display: none" class="admin__fieldset-wrapper order-additional-area"> - <?php echo $block->getChildHtml('additional_area') ?> - </div> - <div id="order-search" style="display: none" class="admin__fieldset-wrapper order-search-items"> - <?php echo $block->getChildHtml('search') ?> - </div> + <div id="order-additional_area" style="display: none" class="admin__page-section order-additional-area"> + <?php echo $block->getChildHtml('additional_area') ?> + </div> - <div id="order-items" class="admin__fieldset-wrapper order-items" data-mage-init='{"loader": {}}'> - <?php echo $block->getChildHtml('items') ?> - </div> + <div id="order-search" style="display: none" class="admin__page-section order-search-items"> + <?php echo $block->getChildHtml('search') ?> + </div> - <div id="order-errors" class="order-errors"><?php echo $block->getChildHtml('errors') ?></div> + <section id="order-items" class="admin__page-section order-items" data-mage-init='{"loader": {}}'> + <?php echo $block->getChildHtml('items') ?> + </section> - <div id="order-form_account" class="admin__fieldset-wrapper order-account-information"> - <?php echo $block->getChildHtml('form_account') ?> - </div> + <div id="order-errors" class="order-errors"><?php echo $block->getChildHtml('errors') ?></div> - <div id="order-addresses" class="admin__fieldset-wrapper order-addresses"> - <div class="admin__fieldset-wrapper-title"> - <strong class="title"><?php echo __('Address Information') ?></strong> + <section id="order-form_account" class="admin__page-section order-account-information"> + <?php echo $block->getChildHtml('form_account') ?> + </section> + + <section id="order-addresses" class="admin__page-section order-addresses"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Address Information') ?></span> + </div> + <div class="admin__page-section-content"> + <div id="order-billing_address" class="admin__page-section-item order-billing-address"> + <?php echo $block->getChildHtml('billing_address') ?> </div> - <div class="admin__fieldset-wrapper-content"> - <div id="order-billing_address" class="order-billing-address"> - <?php echo $block->getChildHtml('billing_address') ?> - </div> - <div id="order-shipping_address" class="order-shipping-address"> - <?php echo $block->getChildHtml('shipping_address') ?> - </div> + <div id="order-shipping_address" class="admin__page-section-item order-shipping-address"> + <?php echo $block->getChildHtml('shipping_address') ?> </div> </div> + </section> - <div id="order-methods" class="admin__fieldset-wrapper order-methods"> - <div class="admin__fieldset-wrapper-title"> - <strong class="title"><?php echo __('Payment & Shipping Information') ?></strong> + <section id="order-methods" class="admin__page-section order-methods"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Information') ?></span> + </div> + <div class="admin__page-section-content"> + <div id="order-billing_method" class="admin__page-section-item order-billing-method"> + <?php echo $block->getChildHtml('billing_method') ?> </div> - <div class="admin__fieldset-wrapper-content"> - <div id="order-billing_method" class="order-billing-method"> - <?php echo $block->getChildHtml('billing_method') ?> - </div> - <div id="order-shipping_method" class="order-shipping-method"> - <?php echo $block->getChildHtml('shipping_method') ?> - </div> + <div id="order-shipping_method" class="admin__page-section-item order-shipping-method"> + <?php echo $block->getChildHtml('shipping_method') ?> </div> </div> + </section> - <?php if ($block->getChildBlock('card_validation')): ?> - <div id="order-card_validation" class="admin__fieldset-wrapper order-card-validation"> - <?php echo $block->getChildHtml('card_validation') ?> - </div> - <?php endif; ?> + <?php if ($block->getChildBlock('card_validation')): ?> + <section id="order-card_validation" class="admin__page-section order-card-validation"> + <?php echo $block->getChildHtml('card_validation') ?> + </section> + <?php endif; ?> - <?php echo $block->getChildHtml('gift_options') ?> + <?php echo $block->getChildHtml('gift_options') ?> - <div class="admin__fieldset-wrapper order-summary"> - <div class="admin__fieldset-wrapper-title"> - <strong class="title"><?php echo __('Order Total') ?></strong> - </div> - <div class="admin__fieldset-wrapper-content"> - <div class="order-history"> - <fieldset class="admin__fieldset" id="order-comment"> - <legend class="admin__legend"><span><?php echo __('Order History') ?></span></legend> - <br> - <?php echo $block->getChildHtml('comment') ?> - </fieldset> - </div> - <div class="order-totals"> - <fieldset id="order-totals" class="order-totals-content admin__fieldset"> - <?php echo $block->getChildHtml('totals') ?> - </fieldset> - </div> - </div> + <section class="admin__page-section order-summary"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Order Total') ?></span> </div> - - </div> + <div class="admin__page-section-content"> + <fieldset class="admin__fieldset order-history" id="order-comment"> + <legend class="admin__legend"><span><?php echo __('Order History') ?></span></legend> + <br> + <?php echo $block->getChildHtml('comment') ?> + </fieldset> + <fieldset id="order-totals" class="admin__fieldset order-totals"> + <?php echo $block->getChildHtml('totals') ?> + </fieldset> + </div> + </section> </div> <?php if ($block->getCustomerId()): ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml index 23f4f8379ceaf37ae403c6e73ac3ea205f88398e..8fa45617a3a04a5de8cd988582c19efbf43dceda 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml @@ -5,12 +5,11 @@ */ ?> -<div class="admin__fieldset-wrapper-title <?php echo $block->getHeaderCssClass() ?>"> +<div class="admin__page-section-title <?php echo $block->getHeaderCssClass() ?>"> <span class="title"><?php echo $block->getHeaderText() ?></span> <div class="actions"></div> </div> - -<div id="customer_account_fieds" class="admin__fieldset-wrapper-content"> +<div id="customer_account_fieds" class="admin__page-section-content"> <?php echo $block->getForm()->getHtml() ?> </div> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/items.phtml index e2b9bd096a03c7f5f6c414b8cc112977f852bc1f..bb7e4b3597c6ee7c9162666bc1dbf411155a7ee7 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/items.phtml @@ -8,7 +8,7 @@ ?> -<div class="admin__fieldset-wrapper-title"> +<div class="admin__page-section-title"> <strong class="title"><?php echo $block->getHeaderText() ?></strong> <div class="actions"> <?php echo $block->getButtonsHtml() ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml index d6c4a2dd5a591b2325af448049f8087cb8653bd3..aaf605a22ce9a659942499c8081832f5b26e92d1 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml @@ -16,7 +16,7 @@ <?php $_items = $block->getItems() ?> <?php if (empty($_items)): ?> <div class="grid" id="order-items_grid"> - <table class="data-table table-info order-tables"> + <table class="data-table admin__table-primary order-tables"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> @@ -40,11 +40,11 @@ <div class="grid" id="order-items_grid"> <div class="hor-scroll"> <?php if (count($_items)>10): ?> - <div class="actions update"> - <?php echo $block->getButtonHtml(__('Update Items and Qty\'s'), 'order.itemsUpdate()'); ?> + <div class="actions update actions-update"> + <?php echo $block->getButtonHtml(__('Update Items and Qty\'s'), 'order.itemsUpdate()', 'action-secondary'); ?> </div> <?php endif; ?> - <table class="data-table table-info order-tables"> + <table class="data-table admin__table-primary order-tables"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> @@ -75,8 +75,8 @@ <tr> <td class="col-product"> <span id="order_item_<?php echo $_item->getId() ?>_title"><?php echo $block->escapeHtml($_item->getName()) ?></span> - <div> - <strong><?php echo __('SKU') ?>:</strong> + <div class="product-sku-block"> + <span><?php echo __('SKU') ?>:</span> <?php echo implode('<br />', $this->helper('Magento\Catalog\Helper\Data')->splitSku($block->escapeHtml($_item->getSku()))); ?> </div> <div class="product-configure-block"> @@ -140,7 +140,7 @@ </td> <td class="col-actions last"> <select class="admin__control-select" name="item[<?php echo $_item->getId() ?>][action]"> - <option value=""></option> + <option value=""><?php echo __('Please select') ?></option> <option value="remove"><?php echo __('Remove') ?></option> <?php if ($block->getCustomerId() && $block->getMoveToCustomerStorage()): ?> <option value="cart"><?php echo __('Move to Shopping Cart') ?></option> @@ -170,7 +170,7 @@ <?php endforeach; ?> <?php if ($hasMessageError):?> - <tr class="col-messages-error"> + <tr class="row-messages-error"> <td colspan="100"> <!-- ToDo UI: remove the 100 --> <?php foreach ($_item->getMessage(false) as $message): if (empty($message)) { diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml index 7ccbfbb6bd3ec7da874f9ed621c5a736d1cdc132..f1e4430c69ff5937b7a0028d063594639ee27c66 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/shipping/method/form.phtml @@ -52,7 +52,7 @@ </dl> </div> <?php if ($_rate = $block->getActiveMethodRate()): ?> - <div id="order-shipping-method-info"> + <div id="order-shipping-method-info" class="order-shipping-method-info"> <dl class="admin__order-shipment-methods"> <dt class="admin__order-shipment-methods-title"> <?php echo $block->escapeHtml($block->getCarrierName($_rate->getCarrier())) ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml index c3eaf03a4c25526c7211116d86654dcb6e85a935..9ae2ac048ef6aa9e6df1ffa0b6b1f73d893fa9bc 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml @@ -9,7 +9,7 @@ ?> <?php /* @var $block \Magento\Sales\Block\Adminhtml\Order\Create\Sidebar\AbstractSidebar */ ?> <div class="create-order-sidebar-block" id="sidebar_data_<?php echo $block->getDataId() ?>"> - <div class="head"> + <div class="head sidebar-title-block"> <a href="#" class="action-refresh" title="<?php echo $block->escapeHtml(__('Refresh')); ?>" onclick="order.loadArea('sidebar_<?php echo $block->getDataId() ?>', 'sidebar_data_<?php echo $block->getDataId() ?>');return false;"> @@ -23,7 +23,7 @@ <div class="content"> <div class="auto-scroll"> <?php if ($block->getItemCount()): ?> - <table class="table-info"> + <table class="admin__table-primary"> <thead> <tr> <th class="col-item"><?php echo __('Item') ?></th> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/form.phtml index b876ba145accb78c81f8140980e95b76bfb8f1e7..f13fd7a04b50b05f720db68d44501be2c189c928 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/form.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/form.phtml @@ -13,58 +13,60 @@ <?php echo $block->getChildHtml('order_info') ?> - <?php if (!$_order->getIsVirtual()): ?> - <div class="clearfix"> - <?php endif; ?> - + <section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Method') ?></span> + </div> + <div class="admin__page-section-content"> <?php if (!$_order->getIsVirtual()): ?> - <div class="order-payment-method"> + <div class="admin__page-section-item order-payment-method"> <?php else: ?> - <div class="order-payment-method order-payment-method-virtual"> + <div class="admin__page-section-item order-payment-method order-payment-method-virtual"> <?php endif; ?> <?php /* Billing Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Payment Information') ?></span> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Payment Information') ?></span> + </div> + <div class="admin__page-section-item-content"> + <div class="order-payment-method-title"><?php echo $block->getChildHtml('order_payment') ?></div> + <div class="order-payment-currency"> + <?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?> + </div> + <div class="order-payment-additional"> + <?php echo $block->getChildHtml('order_payment_additional'); ?> </div> - <div><?php echo $block->getChildHtml('order_payment') ?></div> - <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> - <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> </div> - </div> <?php if (!$_order->getIsVirtual()): ?> - <div class="order-shipping-address"> + <div class="admin__page-section-item order-shipping-address"> <?php /* Shipping Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Shipping Information') ?></span> - </div> - <div class="shipping-description-wrapper"> - <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> - <div class="shipping-description-content"> - <?php echo __('Total Shipping Charges'); ?>: + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipping Information') ?></span> + </div> + <div class="admin__page-section-item-content shipping-description-wrapper"> + <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> + <div class="shipping-description-content"> + <?php echo __('Total Shipping Charges'); ?>: - <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax($block->getSource()->getStoreId())): ?> - <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> - <?php else: ?> - <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> - <?php endif; ?> - <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax($block->getSource()->getStoreId())): ?> + <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> + <?php else: ?> + <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> + <?php endif; ?> + <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> - <?php echo $_excl; ?> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices($block->getSource()->getStoreId()) && $_incl != $_excl): ?> - (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) - <?php endif; ?> - </div> + <?php echo $_excl; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices($block->getSource()->getStoreId()) && $_incl != $_excl): ?> + (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) + <?php endif; ?> </div> </div> </div> <?php endif; ?> - - </div><?php /* opening div can be in app\code\Magento\Sales\view\adminhtml\order\view\info.phtml or above */?> + </div> + </section> <div id="creditmemo_item_container"> <?php echo $block->getChildHtml('order_items') ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml index c09ee04d9435d03df15868073eb92d7e82631786..82770b4f3fa45ba239c13dfb673a1dbb8f5d1bb3 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml @@ -9,14 +9,14 @@ ?> <?php $_items = $block->getCreditmemo()->getAllItems() ?> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Items to Refund') ?></span> </div> <?php if (count($_items)) : ?> <div class="grid"> - <table cellspacing="0" class="data order-tables"> + <table class="data-table admin__table-primary order-creditmemo-tables"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> @@ -61,40 +61,66 @@ <?php echo __('No Items To Refund') ?> </div> <?php endif; ?> -</div> +</section> <?php $orderTotalBar = $block->getChildHtml('order_totalbar'); ?> <?php if (!empty($orderTotalBar)): ?> -<div class="fieldset-wrapper"> +<section class="fieldset-wrapper"> <?php echo $orderTotalBar; ?> -</div> +</section> <?php endif; ?> -<div class="clearfix"> +<section class="admin__page-section"> <input type="hidden" name="creditmemo[do_offline]" id="creditmemo_do_offline" value="0" /> - <div class="order-comments-history"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"><span class="title"><?php echo __('Credit Memo Comments') ?></span></div> - <fieldset id="history_form"> - <label class="normal" for="creditmemo_comment_text"><?php echo __('Credit Memo Comments') ?></label><br/> - <textarea id="creditmemo_comment_text" name="creditmemo[comment_text]" rows="3" cols="5"><?php echo $block->getCreditmemo()->getCommentText(); ?></textarea> - </fieldset> - </div> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Order Total') ?></span> </div> - <div class="order-totals creditmemo-totals"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"><span class="title"><?php echo __('Refund Totals') ?></span></div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-comments-history"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Credit Memo Comments') ?></span> + </div> + <div id="history_form" class="admin__fieldset-wrapper-content"> + <div class="admin__field"> + <label class="normal admin__field-label" + for="creditmemo_comment_text"><?php echo __('Comment Text') ?></label> + <div class="admin__field-control"> + <textarea id="creditmemo_comment_text" + class="admin__control-textarea" + name="creditmemo[comment_text]" + rows="3" + cols="5"><?php echo $block->getCreditmemo()->getCommentText(); ?></textarea> + </div> + </div> + </div> + </div> + <div class="admin__page-section-item order-totals creditmemo-totals"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Refund Totals') ?></span> + </div> <?php echo $block->getChildHtml('creditmemo_totals') ?> <div class="order-totals-actions"> - <div class="field choice field-append-comments"> - <input id="notify_customer" name="creditmemo[comment_customer_notify]" value="1" type="checkbox" /> - <label for="notify_customer"><span><?php echo __('Append Comments') ?></span></label> + <div class="field choice admin__field admin__field-option field-append-comments"> + <input id="notify_customer" + class="admin__control-checkbox" + name="creditmemo[comment_customer_notify]" + value="1" + type="checkbox" /> + <label for="notify_customer" class="admin__field-label"> + <span><?php echo __('Append Comments') ?></span> + </label> </div> <?php if ($block->canSendCreditmemoEmail()):?> - <div class="field choice field-email-copy"> - <input id="send_email" name="creditmemo[send_email]" value="1" type="checkbox" /> - <label for="send_email"><span><?php echo __('Email Copy of Credit Memo') ?></span></label> + <div class="field choice admin__field admin__field-option field-email-copy"> + <input id="send_email" + class="admin__control-checkbox" + name="creditmemo[send_email]" + value="1" + type="checkbox" /> + <label for="send_email" class="admin__field-label"> + <span><?php echo __('Email Copy of Credit Memo') ?></span> + </label> </div> <?php endif; ?> <?php echo $block->getChildHtml('submit_before') ?> @@ -106,7 +132,7 @@ </div> </div> </div> -</div> +</section> <script> require(['jquery', 'prototype'], function(jQuery){ diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items/renderer/default.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items/renderer/default.phtml index 76ec308d8b6696ecb466071cb290bd23d4a7fd3f..c238f2478bffae8180f6391914320fdacdee4db6 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items/renderer/default.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items/renderer/default.phtml @@ -19,13 +19,20 @@ <?php if ($block->canParentReturnToStock($_item)) : ?> <td class="col-return-to-stock"> <?php if ($block->canReturnItemToStock($_item)) : ?> - <input type="checkbox" name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][back_to_stock]" value="1"<?php if ($_item->getBackToStock()):?> checked<?php endif;?>/> + <input type="checkbox" + class="admin__control-checkbox" + name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][back_to_stock]" + value="1"<?php if ($_item->getBackToStock()):?> checked<?php endif;?>/> + <label class="admin__field-label"></label> <?php endif; ?> </td> <?php endif; ?> - <td class="col-refund"> + <td class="col-refund col-qty"> <?php if ($block->canEditQty()) : ?> - <input type="text" class="input-text qty-input" name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][qty]" value="<?php echo $_item->getQty()*1 ?>"/> + <input type="text" + class="input-text admin__control-text qty-input" + name="creditmemo[items][<?php echo $_item->getOrderItemId() ?>][qty]" + value="<?php echo $_item->getQty()*1 ?>"/> <?php else : ?> <?php echo $_item->getQty()*1 ?> <?php endif; ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/totals/adjustments.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/totals/adjustments.phtml index 4b7f73a40590b4ae166748ce1cb2c756ab0b7467..8ae81b1a6d0c0d5046ea7ff7ea45a1bcec2b9780 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/totals/adjustments.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/totals/adjustments.phtml @@ -11,52 +11,69 @@ <?php if ($_source): ?> <tr> <td class="label"><?php echo $block->getShippingLabel() ?><div id="shipping_amount_adv"></div></td> - <td><input type="text" name="creditmemo[shipping_amount]" value="<?php echo $block->getShippingAmount()?>" class="input-text not-negative-amount" id="shipping_amount" /></td> + <td> + <input type="text" + name="creditmemo[shipping_amount]" + value="<?php echo $block->getShippingAmount()?>" + class="input-text admin__control-text not-negative-amount" + id="shipping_amount" /> + </td> </tr> <tr> <td class="label"><?php echo __('Adjustment Refund') ?><div id="adjustment_positive_adv"></div></td> - <td><input type="text" name="creditmemo[adjustment_positive]" value="<?php echo $_source->getBaseAdjustmentFeePositive()*1 ?>" class="input-text not-negative-amount" id="adjustment_positive" /></td> + <td> + <input type="text" + name="creditmemo[adjustment_positive]" + value="<?php echo $_source->getBaseAdjustmentFeePositive()*1 ?>" + class="input-text admin__control-text not-negative-amount" + id="adjustment_positive" /> + </td> </tr> <tr> <td class="label"><?php echo __('Adjustment Fee') ?><div id="adjustment_negative_adv"></div></td> - <td><input type="text" name="creditmemo[adjustment_negative]" value="<?php echo $_source->getBaseAdjustmentFeeNegative()*1 ?>" class="input-text not-negative-amount" id="adjustment_negative"/> - <script> -require(['prototype'], function(){ + <td> + <input type="text" + name="creditmemo[adjustment_negative]" + value="<?php echo $_source->getBaseAdjustmentFeeNegative()*1 ?>" + class="input-text admin__control-text not-negative-amount" + id="adjustment_negative"/> + <script> + require(['prototype'], function(){ -//<![CDATA[ -Validation.addAllThese([ - ['not-negative-amount', '<?php echo __('Please enter a positive number in this field.') ?>', function(v) { - if(v.length) - return /^\s*\d+([,.]\d+)*\s*%?\s*$/.test(v); - else - return true; - }] -]); + //<![CDATA[ + Validation.addAllThese([ + ['not-negative-amount', '<?php echo __('Please enter a positive number in this field.') ?>', function(v) { + if(v.length) + return /^\s*\d+([,.]\d+)*\s*%?\s*$/.test(v); + else + return true; + }] + ]); -if ($('shipping_amount')) { - $('shipping_amount').advaiceContainer = $('shipping_amount_adv'); - unblockSubmit('shipping_amount'); -} -if ($('adjustment_positive')) { - $('adjustment_positive').advaiceContainer = $('adjustment_positive_adv'); - unblockSubmit('adjustment_positive'); -} -if ($('adjustment_negative')) { - $('adjustment_negative').advaiceContainer = $('adjustment_negative_adv'); - unblockSubmit('adjustment_negative'); -} + if ($('shipping_amount')) { + $('shipping_amount').advaiceContainer = $('shipping_amount_adv'); + unblockSubmit('shipping_amount'); + } + if ($('adjustment_positive')) { + $('adjustment_positive').advaiceContainer = $('adjustment_positive_adv'); + unblockSubmit('adjustment_positive'); + } + if ($('adjustment_negative')) { + $('adjustment_negative').advaiceContainer = $('adjustment_negative_adv'); + unblockSubmit('adjustment_negative'); + } -function unblockSubmit(id) { - $(id).observe('focus', function(event) { - if ($$('button[class="scalable update-button disabled"]').size() > 0) { - enableElements('submit-button'); - } - }); -} -//]]> + function unblockSubmit(id) { + $(id).observe('focus', function(event) { + if ($$('button[class="scalable update-button disabled"]').size() > 0) { + enableElements('submit-button'); + } + }); + } + //]]> -}); -</script> + }); + </script> </td> </tr> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/form.phtml index df2f092e4f8aa839320ce77450ec4fceab97d5e4..ee8ec752df51752961a3b64a2bf415a4a3174ccb 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/form.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/form.phtml @@ -9,51 +9,56 @@ ?> <?php $_order = $block->getCreditmemo()->getOrder() ?> <?php echo $block->getChildHtml('order_info') ?> -<div class="clearfix"> -<?php if (!$_order->getIsVirtual()): ?> -<div class="order-payment-method"> -<?php else: ?> -<div class="order-payment-method order-payment-method-virtual"> -<?php endif; ?> - <?php /* Billing Address */?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Payment Information') ?></span> - </div> - <div><?php echo $block->getChildHtml('order_payment') ?></div> - <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> - <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> +<section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Method') ?></span> </div> -</div> -<?php if (!$_order->getIsVirtual()): ?> -<div class="order-shipping-address"> - <?php /* Shipping Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Shipping Information') ?></span> + <div class="admin__page-section-content"> + + <?php if (!$_order->getIsVirtual()): ?> + <div class="admin__page-section-item order-payment-method"> + <?php else: ?> + <div class="admin__page-section-item order-payment-method order-payment-method-virtual"> + <?php endif; ?> + <?php /* Billing Address */?> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Payment Information') ?></span> + </div> + <div class="admin__page-section-item-content"> + <div><?php echo $block->getChildHtml('order_payment') ?></div> + <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> + <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> + </div> </div> - <div class="shipping-description-wrapper"> - <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> - <div class="shipping-description-content"> - <?php echo __('Total Shipping Charges'); ?>: - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> - <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> - <?php else: ?> - <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> - <?php endif; ?> - <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> + <?php if (!$_order->getIsVirtual()): ?> + <div class="admin__page-section-item order-shipping-address"> + <?php /* Shipping Address */ ?> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipping Information') ?></span> + </div> + <div class="shipping-description-wrapper admin__page-section-item-content"> + <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> + <div class="shipping-description-content"> + <?php echo __('Total Shipping Charges'); ?>: - <?php echo $_excl; ?> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> - (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) - <?php endif; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> + <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> + <?php else: ?> + <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> + <?php endif; ?> + <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> + + <?php echo $_excl; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> + (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) + <?php endif; ?> + </div> </div> </div> + <?php endif; ?> </div> -</div> -<?php endif; ?> -</div> +</section> <?php $_items = $block->getCreditmemo()->getAllItems() ?> <?php if (count($_items)): ?> @@ -61,24 +66,30 @@ <?php echo $block->getChildHtml('creditmemo_items') ?> </div> <?php else: ?> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Items Refunded') ?></span> </div> - <div class="no-items"><?php echo __('No Items') ?></div> -</div> + <div class="no-items admin__page-section-content"><?php echo __('No Items') ?></div> +</section> <?php endif; ?> -<div class="clearfix"> - <div class="order-comments-history"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"><span class="title"><?php echo __('Credit Memo History') ?></span></div> - <fieldset><?php echo $block->getChildHtml('order_comments') ?></fieldset> - </div> + +<section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Memo Total') ?></span> </div> - <div class="order-totals"> - <div class="fieldset-wrapper" id="history_form"> - <div class="fieldset-wrapper-title"><span class="title"><?php echo __('Credit Memo Totals') ?></span></div> - <div><?php echo $block->getChildHtml('creditmemo_totals') ?></div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-comments-history"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Credit Memo History') ?></span> + </div> + <div class="admin__page-section-item-content"><?php echo $block->getChildHtml('order_comments') ?></div> + </div> + <div class="admin__page-section-item order-totals" id="history_form"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Credit Memo Totals') ?></span> + </div> + <div class="admin__page-section-content"><?php echo $block->getChildHtml('creditmemo_totals') ?></div> </div> </div> -</div> +</section> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/items.phtml index a75e830aaacb88ff6ec19021c620544ef227bac2..3618871f0c7cac6da817fc5fe72ca8073cb97777 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/view/items.phtml @@ -8,12 +8,12 @@ ?> <?php $_items = $block->getCreditmemo()->getAllItems() ?> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<div class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Items Refunded') ?></span> </div> - <div class="grid"> - <table cellspacing="0" class="data"> + <div class="admin__page-section-content"> + <table class="data-table admin__table-primary order-creditmemo-tables"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/giftoptions.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/giftoptions.phtml index c837566257032cc8cd89c1c7e5be2e0a8d0d4edc..bab344f25065b2bfba1be65196fa2a28068d6044 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/giftoptions.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/giftoptions.phtml @@ -8,8 +8,8 @@ ?> <?php if ($block->getChildHtml()): ?> -<div class="admin__fieldset-wrapper order-gift-options"> - <div class="admin__fieldset-wrapper-title"><strong class="title"><?php echo __('Gift Options') ?></strong></div> +<section class="admin__page-section order-gift-options"> + <div class="admin__page-section-title"><strong class="title"><?php echo __('Gift Options') ?></strong></div> <?php echo $block->getChildHtml() ?> -</div> +</section> <?php endif ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/form.phtml index ce938f85d2764a1168ee9fb00d92ad9d42a2f84c..b0319ea9791f7b35afe27d1e647e6e9859448e03 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/form.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/form.phtml @@ -7,68 +7,72 @@ // @codingStandardsIgnoreFile ?> -<form id="edit_form" method="post" action="<?php echo $block->getSaveUrl() ?>"> +<form id="edit_form" class="order-invoice-edit" method="post" action="<?php echo $block->getSaveUrl() ?>"> <?php echo $block->getBlockHtml('formkey')?> <?php $_order = $block->getInvoice()->getOrder() ?> <?php echo $block->getChildHtml('order_info') ?> - <?php if (!$_order->getIsVirtual()): ?> - <div class="clearfix"> - <?php endif; ?> - <div class="order-payment-method<?php if ($_order->getIsVirtual()): ?> order-payment-method-virtual<?php endif; ?>"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Payment Information') ?></span> - </div> - <div><?php echo $block->getChildHtml('order_payment') ?></div> - <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> - <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> + <section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Method') ?></span> </div> - </div> - <?php if (!$_order->getIsVirtual()): ?> - <div class="order-shipping-address"> - <?php /*Shipping Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Shipping Information') ?></span> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-payment-method<?php if ($_order->getIsVirtual()): ?> order-payment-method-virtual<?php endif; ?>"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Payment Information') ?></span> + </div> + <div class="admin__page-section-item-content"> + <div><?php echo $block->getChildHtml('order_payment') ?></div> + <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> + <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> + </div> </div> - <div class="shipping-description-wrapper"> - <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> - <div class="shipping-description-content"> - <?php echo __('Total Shipping Charges'); ?>: + <?php if (!$_order->getIsVirtual()): ?> + <div class="admin__page-section-item order-shipping-address"> + <?php /*Shipping Address */ ?> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipping Information') ?></span> + </div> + <div class="admin__page-section-item-content"> + <div class="shipping-description-wrapper"> + <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> + <div class="shipping-description-content"> + <?php echo __('Total Shipping Charges'); ?>: - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> - <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> - <?php else: ?> - <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> - <?php endif; ?> - <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> + <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> + <?php else: ?> + <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> + <?php endif; ?> + <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> - <?php echo $_excl; ?> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> - (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) + <?php echo $_excl; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> + (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) + <?php endif; ?> + </div> + </div> + <?php if ($block->canCreateShipment() && $block->canShipPartiallyItem()): ?> + <div class="admin__field admin__field-option"> + <input type="checkbox" name="invoice[do_shipment]" id="invoice_do_shipment" value="1" + class="admin__control-checkbox" <?php echo $block->hasInvoiceShipmentTypeMismatch() ? ' disabled="disabled"' : '' ?> /> + <label for="invoice_do_shipment" + class="admin__field-label"><span><?php echo __('Create Shipment') ?></span></label> + </div> + <?php if ($block->hasInvoiceShipmentTypeMismatch()): ?> + <small><?php echo __('Invoice and shipment types do not match for some items on this order. You can create a shipment only after creating the invoice.') ?></small> + <?php endif; ?> <?php endif; ?> + <div id="tracking" style="display:none;"><?php echo $block->getChildHtml('tracking', false) ?></div> </div> </div> - <?php if ($block->canCreateShipment() && $block->canShipPartiallyItem()): ?> - <div> - <label for="invoice_do_shipment" class="normal"><?php echo __('Create Shipment') ?></label> - <input type="checkbox" name="invoice[do_shipment]" id="invoice_do_shipment" value="1" <?php echo $block->hasInvoiceShipmentTypeMismatch() ? ' disabled="disabled"' : '' ?> /> - </div> - <?php if ($block->hasInvoiceShipmentTypeMismatch()): ?> - <small><?php echo __('Invoice and shipment types do not match for some items on this order. You can create a shipment only after creating the invoice.') ?></small> - <?php endif; ?> <?php endif; ?> - <div id="tracking" style="display:none;"><?php echo $block->getChildHtml('tracking', false) ?></div> </div> - </div> - <?php endif; ?> - - </div> + </section> - <div id="invoice_item_container"> + <section id="invoice_item_container"> <?php echo $block->getChildHtml('order_items') ?> - </div> + </section> </form> <script> require(['prototype'], function(){ diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml index 118eca64172985d63ab5794a01f691cd21ada117..883f04cb7f3eb528cde7db31c8254c1dc197a566 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml @@ -8,13 +8,13 @@ ?> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <?php $_itemsGridLabel = $block->getForcedShipmentCreate() ? 'Items to Invoice and Ship' : 'Items to Invoice'; ?> <span class="title"><?php echo __('%1', $_itemsGridLabel) ?></span> </div> - <div class="grid"> - <table cellspacing="0" class="data"> + <div class="admin__page-section-content grid"> + <table class="data-table admin__table-primary order-invoice-tables"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> @@ -50,45 +50,55 @@ <?php endforeach; ?> </table> </div> -</div> +</section> <?php $orderTotalBar = $block->getChildHtml('order_totalbar'); ?> <?php if (!empty($orderTotalBar)): ?> -<div class="fieldset-wrapper"> +<section class="admin__page-section"> <?php echo $orderTotalBar; ?> -</div> +</section> <?php endif; ?> -<div class="clearfix"> - <div class="order-comments-history"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Order Total') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-comments-history"> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Invoice History') ?></span> </div> - <div id="history_form" class="order-history-form"> - <label class="normal" for="invoice_comment_text"><?php echo __('Invoice Comments') ?></label> - <textarea id="invoice_comment_text" name="invoice[comment_text]" rows="3" cols="5"><?php echo $block->getInvoice()->getCommentText(); ?></textarea> + <div id="history_form" class="admin__page-section-item-content order-history-form"> + <div class="admin__field"> + <label for="invoice_comment_text" class="admin__field-label"> + <span><?php echo __('Invoice Comments') ?></span> + </label> + <div class="admin__field-control"> + <textarea id="invoice_comment_text" name="invoice[comment_text]" class="admin__control-textarea" + rows="3" cols="5"><?php echo $block->getInvoice()->getCommentText(); ?></textarea> + </div> + </div> </div> </div> - </div> - <div class="order-totals"> - <div class="fieldset-wrapper" id="invoice_totals"> - <div class="fieldset-wrapper-title"> + <div id="invoice_totals" class="admin__page-section-item order-totals"> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Invoice Totals') ?></span> </div> - <div class="order-totals-actions"> + <div class="admin__page-section-item-content order-totals-actions"> <?php echo $block->getChildHtml('invoice_totals') ?> <?php if ($block->isCaptureAllowed()): ?> <?php if ($block->canCapture()):?> - <div> - <!-- - <label for="invoice_do_capture" class="normal"><?php echo __('Capture Amount') ?></label> - <input type="checkbox" name="invoice[do_capture]" id="invoice_do_capture" value="1" checked/> - --> - <label for="invoice_do_capture" class="normal"><?php echo __('Amount') ?></label> - <select name="invoice[capture_case]"> + <div class="admin__field"> + <?php + /* + <label for="invoice_do_capture" class="normal"><?php echo __('Capture Amount') ?></label> + <input type="checkbox" name="invoice[do_capture]" id="invoice_do_capture" value="1" checked/> + */ + ?> + <label for="invoice_do_capture" class="admin__field-label"><?php echo __('Amount') ?></label> + <select class="admin__control-select" name="invoice[capture_case]"> <option value="online"><?php echo __('Capture Online') ?></option> <option value="offline"><?php echo __('Capture Offline') ?></option> <option value="not_capture"><?php echo __('Not Capture') ?></option> @@ -99,14 +109,16 @@ <div><?php echo __('The invoice will be created offline without the payment gateway.') ?></div> <?php endif?> <?php endif; ?> - <div class="field choice field-append"> - <input id="notify_customer" name="invoice[comment_customer_notify]" value="1" type="checkbox" /> - <label class="normal" for="notify_customer"><?php echo __('Append Comments') ?></label> + <div class="admin__field admin__field-option field-append"> + <input id="notify_customer" name="invoice[comment_customer_notify]" value="1" type="checkbox" + class="admin__control-checkbox" /> + <label class="admin__field-label" for="notify_customer"><?php echo __('Append Comments') ?></label> </div> <?php if ($block->canSendInvoiceEmail()): ?> - <div class="field choice field-email"> - <input id="send_email" name="invoice[send_email]" value="1" type="checkbox" /> - <label class="normal" for="send_email"><?php echo __('Email Copy of Invoice') ?></label> + <div class="admin__field admin__field-option field-email"> + <input id="send_email" name="invoice[send_email]" value="1" type="checkbox" + class="admin__control-checkbox" /> + <label class="admin__field-label" for="send_email"><?php echo __('Email Copy of Invoice') ?></label> </div> <?php endif; ?> <div class="actions"> @@ -115,7 +127,7 @@ </div> </div> </div> -</div> +</section> <script> require(['jquery', 'prototype'], function($){ diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items/renderer/default.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items/renderer/default.phtml index f416f1ba7b5983e955099a45ce5c887a23d5ae2e..45b53a6d05ea0c65132c86050ed7ab03d30dc530 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items/renderer/default.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items/renderer/default.phtml @@ -17,7 +17,9 @@ <td class="col-qty"><?php echo $block->getColumnHtml($_item, 'qty') ?></td> <td class="col-qty-invoice"> <?php if ($block->canEditQty()) : ?> - <input type="text" class="input-text qty-input" name="invoice[items][<?php echo $_item->getOrderItemId() ?>]" value="<?php echo $_item->getQty()*1 ?>"/> + <input type="text" class="input-text admin__control-text qty-input" + name="invoice[items][<?php echo $_item->getOrderItemId() ?>]" + value="<?php echo $_item->getQty()*1 ?>"/> <?php else : ?> <?php echo $_item->getQty()*1 ?> <?php endif; ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/form.phtml index d1a08dfeb6d6b4e2d6f654caf88e93922064cc2b..cd625596b541da95d9d24de7069c0d33c71117af 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/form.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/form.phtml @@ -11,84 +11,87 @@ <?php $_order = $_invoice->getOrder() ?> <?php echo $block->getChildHtml('order_info') ?> -<?php /* opening div is in app\code\Magento\Sales\view\adminhtml\order\view\info.phtml */?> - -<?php if (!$_order->getIsVirtual()): ?> -<div class="clearfix"> <?php /* if opening div from app\code\Magento\Sales\view\adminhtml\order\view\info.phtml was closed there */?> -<?php endif; ?> - - <div class="order-payment-method<?php if ($_order->getIsVirtual()): ?> order-payment-method-virtual<?php endif; ?>"> - <?php /*Billing Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section order-view-billing-shipping"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Method') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-payment-method<?php if ($_order->getIsVirtual()): ?> order-payment-method-virtual<?php endif; ?> admin__fieldset-wrapper"> + <?php /*Billing Address */ ?> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Payment Information') ?></span> </div> - <div><?php echo $block->getChildHtml('order_payment') ?></div> - <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> - <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> + <div class="admin__page-section-item-content"> + <div><?php echo $block->getChildHtml('order_payment') ?></div> + <div class="order-payment-currency"> + <?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?> + </div> + <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> + </div> </div> - </div> - <?php if (!$_order->getIsVirtual()): ?> - <div class="order-shipping-address"> - <?php /*Shipping Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Shipping Information') ?></span> - </div> - <div class="shipping-description-wrapper"> - <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> - <div class="shipping-description-content"> - <?php echo __('Total Shipping Charges'); ?>: + <?php if (!$_order->getIsVirtual()): ?> + <div class="admin__page-section-item order-shipping-address"> + <?php /*Shipping Address */ ?> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipping Information') ?></span> + </div> + <div class="admin__page-section-item-content shipping-description-wrapper"> + <div class="shipping-description-title"> + <?php echo $block->escapeHtml($_order->getShippingDescription()) ?> + </div> + <div class="shipping-description-content"> + <?php echo __('Total Shipping Charges'); ?>: - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> - <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> - <?php else: ?> - <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> - <?php endif; ?> - <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> + <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> + <?php else: ?> + <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> + <?php endif; ?> + <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> - <?php echo $_excl; ?> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> - (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) - <?php endif; ?> - <div><?php echo $block->getChildHtml('shipment_tracking') ?></div> + <?php echo $_excl; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> + (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) + <?php endif; ?> + <div><?php echo $block->getChildHtml('shipment_tracking') ?></div> + </div> </div> </div> - </div> - </div> - <?php endif; ?> + <?php endif; ?> -</div> + </div> +</section> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Items Invoiced') ?></span> </div> - <div id="invoice_item_container"> + <div id="invoice_item_container" class="admin__page-section-content"> <?php echo $block->getChildHtml('invoice_items') ?> </div> -</div> +</section> -<div class="clearfix"> - <div class="order-comments-history"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Order Total') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-comments-history"> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Invoice History') ?></span> </div> - <fieldset> + <div class="admin__page-section-item-content"> <?php echo $block->getChildHtml('order_comments') ?> - </fieldset> + </div> </div> - </div> - <div class="order-totals"> - <div class="fieldset-wrapper" id="history_form"> - <div class="fieldset-wrapper-title"> + <div id="history_form" class="admin__page-section-item order-totals"> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Invoice Totals') ?></span> </div> <?php echo $block->getChildHtml('invoice_totals') ?> </div> </div> -</div> +</section> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/items.phtml index 2dd825764ac916f3940e749d2a81798dea4ae633..9298795db0b62507f426147a6d643a0eefca8d03 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/view/items.phtml @@ -8,7 +8,7 @@ ?> <div class="grid"> - <table class="data order-tables"> + <table class="data-table admin__table-primary order-invoice-tables"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/totals.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/totals.phtml index 06b1e692a036a4ff9d9659e835b81fe4142ca137..45b816084520bbe14c11af4050b0cf5d533156e2 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/totals.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/totals.phtml @@ -15,53 +15,56 @@ <?php echo $block->getChildHtml('footer'); ?> </table> <?php endif;*/ ?> -<table class="data-table table-info order-subtotal"> +<table class="data-table admin__table-secondary order-subtotal-table"> <?php $_totals = $block->getTotals('footer')?> + <?php if ($_totals):?> - <tfoot> - <?php foreach ($block->getTotals('footer') as $_code => $_total): ?> - <?php if ($_total->getBlockName()): ?> - <?php echo $block->getChildHtml($_total->getBlockName(), false); ?> - <?php else:?> - <tr class="col-<?php echo $_code?>"> - <td <?php echo $block->getLabelProperties()?> class="label"> - <strong><?php echo $block->escapeHtml($_total->getLabel()); ?></strong> - </td> - <td <?php echo $block->getValueProperties()?>> - <strong><?php echo $block->formatValue($_total) ?></strong> - </td> - </tr> - <?php endif?> - <?php endforeach?> - </tfoot> + <tfoot> + <?php foreach ($block->getTotals('footer') as $_code => $_total): ?> + <?php if ($_total->getBlockName()): ?> + <?php echo $block->getChildHtml($_total->getBlockName(), false); ?> + <?php else:?> + <tr class="col-<?php echo $_code?>"> + <td <?php echo $block->getLabelProperties()?> class="label"> + <strong><?php echo $block->escapeHtml($_total->getLabel()); ?></strong> + </td> + <td <?php echo $block->getValueProperties()?>> + <strong><?php echo $block->formatValue($_total) ?></strong> + </td> + </tr> + <?php endif?> + <?php endforeach?> + </tfoot> <?php endif?> <?php $_totals = $block->getTotals('')?> <?php if ($_totals):?> - <tbody> - <?php foreach ($_totals as $_code => $_total): ?> - <?php if ($_total->getBlockName()): ?> - <?php echo $block->getChildHtml($_total->getBlockName(), false); ?> - <?php else:?> - <tr class="col-<?php echo $_code?>"> - <td <?php echo $block->getLabelProperties()?> class="label"> - <?php if ($_total->getStrong()):?> - <strong><?php echo $block->escapeHtml($_total->getLabel()); ?></strong> + <tbody> + <?php foreach ($_totals as $_code => $_total): ?> + <?php if ($_total->getBlockName()): ?> + <?php echo $block->getChildHtml($_total->getBlockName(), false); ?> <?php else:?> - <?php echo $block->escapeHtml($_total->getLabel()); ?> + <tr class="col-<?php echo $_code?>"> + <td <?php echo $block->getLabelProperties()?> class="label"> + <?php if ($_total->getStrong()):?> + <strong><?php echo $block->escapeHtml($_total->getLabel()); ?></strong> + <?php else:?> + <?php echo $block->escapeHtml($_total->getLabel()); ?> + <?php endif?> + </td> + + <?php if ($_total->getStrong()):?> + <td <?php echo $block->getValueProperties()?>> + <strong><?php echo $block->formatValue($_total) ?></strong> + </td> + <?php else:?> + <td <?php echo $block->getValueProperties()?>> + <span><?php echo $block->formatValue($_total) ?></span> + </td> + <?php endif?> + </tr> <?php endif?> - </td> - <?php if ($_total->getStrong()):?> - <td <?php echo $block->getValueProperties()?>> - <strong><?php echo $block->formatValue($_total) ?></strong> - <?php else:?> - <td <?php echo $block->getValueProperties()?>> - <?php echo $block->formatValue($_total) ?> - <?php endif?> - </td> - </tr> - <?php endif?> - <?php endforeach?> - </tbody> + <?php endforeach?> + </tbody> <?php endif?> </table> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/form.phtml index 2ccc60117a6ea662ff928690563244c684be7252..ea8956727f637d25ca32d23a10a3aa34648fda2e 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/form.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/form.phtml @@ -4,4 +4,4 @@ * See COPYING.txt for license details. */ ?> -<div class="entry-edit" id="sales_order_view"></div> +<div class="entry-edit order-view" id="sales_order_view"></div> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/giftmessage.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/giftmessage.phtml index a7d7d1552fcb732eda9bf4b0887c83e55ae7e854..9fa3eda8f0d7a93ae165b39bbd96653c44e56ea6 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/giftmessage.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/giftmessage.phtml @@ -9,32 +9,50 @@ ?> <?php if ($block->canDisplayGiftmessage()): ?> <?php $_required = $block->getMessage()->getMessage() != ''?> -<div id="<?php echo $block->getHtmlId() ?>" class="box-left giftmessage-whole-order-container"> +<div id="<?php echo $block->getHtmlId() ?>" class="admin__page-section-content giftmessage-whole-order-container"> <form class="entry-edit form-inline" id="<?php echo $block->getFieldId('form') ?>" action="<?php echo $block->getSaveUrl() ?>"> - <fieldset> + <fieldset class="admin__fieldset"> <legend class="admin__legend"><span><?php echo __('Gift Message for the Entire Order'); ?></span></legend> - <br> + <br/> - <input type="hidden" id="<?php echo $block->getFieldId('type'); ?>" name="<?php echo $block->getFieldName('type'); ?>" value="order" /> + <input type="hidden" id="<?php echo $block->getFieldId('type'); ?>" + name="<?php echo $block->getFieldName('type'); ?>" + value="order"/> - <div class="field field-from-name <?php echo $_required ? 'required' : ''; ?>"> - <label class="label" for="<?php echo $block->getFieldId('sender'); ?>"><span><?php echo __('From Name'); ?></span></label> - <div class="control"> - <input class="input-text <?php echo $_required ? 'required-entry' : ''; ?>" type="text" id="<?php echo $block->getFieldId('sender'); ?>" name="<?php echo $block->getFieldName('sender'); ?>" value="<?php echo $block->escapeHtml($block->getMessage()->getSender()); ?>" /> + <div class="admin__field field-from-name<?php echo $_required ? ' required' : ''; ?>"> + <label class="admin__field-label" + for="<?php echo $block->getFieldId('sender'); ?>"><span><?php echo __('From Name'); ?></span></label> + + <div class="admin__field-control"> + <input class="admin__control-text <?php echo $_required ? 'required-entry' : ''; ?>" type="text" + id="<?php echo $block->getFieldId('sender'); ?>" + name="<?php echo $block->getFieldName('sender'); ?>" + value="<?php echo $block->escapeHtml($block->getMessage()->getSender()); ?>"/> </div> </div> - <div class="field field-to-name <?php echo $_required ? 'required' : ''; ?>"> - <label class="label" for="<?php echo $block->getFieldId('recipient'); ?>"><span><?php echo __('To Name'); ?></span></label> - <div class="control"> - <input class="input-text <?php echo $_required ? 'required-entry' : ''; ?>" type="text" id="<?php echo $block->getFieldId('recipient'); ?>" name="<?php echo $block->getFieldName('recipient'); ?>" value="<?php echo $block->escapeHtml($block->getMessage()->getRecipient()); ?>" /> + <div class="admin__field field-to-name<?php echo $_required ? ' required' : ''; ?>"> + <label class="admin__field-label" + for="<?php echo $block->getFieldId('recipient'); ?>"><span><?php echo __('To Name'); ?></span></label> + + <div class="admin__field-control"> + <input class="admin__control-text <?php echo $_required ? 'required-entry' : ''; ?>" type="text" + id="<?php echo $block->getFieldId('recipient'); ?>" + name="<?php echo $block->getFieldName('recipient'); ?>" + value="<?php echo $block->escapeHtml($block->getMessage()->getRecipient()); ?>"/> </div> </div> - <div class="field field-gift-message"> - <label class="label" for="<?php echo $block->getFieldId('message'); ?>"><span><?php echo __('Gift Message'); ?></span></label> - <div class="control"> - <textarea id="<?php echo $block->getFieldId('message'); ?>" name="<?php echo $block->getFieldName('message') ?>" rows="2" cols="15"><?php echo $block->escapeHtml($block->getMessage()->getMessage()); ?></textarea> + <div class="admin__field field-gift-message"> + <label class="admin__field-label" + for="<?php echo $block->getFieldId('message'); ?>"><span><?php echo __('Gift Message'); ?></span></label> + + <div class="admin__field-control"> + <textarea id="<?php echo $block->getFieldId('message'); ?>" + name="<?php echo $block->getFieldName('message') ?>" + class="admin__control-textarea" + rows="2" + cols="15"><?php echo $block->escapeHtml($block->getMessage()->getMessage()); ?></textarea> </div> </div> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml index a202b3aa0dcee89d76652153dadcd23cb3e2476a..b1c4121b92fc36055dce194757c944a5486fbab3 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml @@ -7,38 +7,71 @@ // @codingStandardsIgnoreFile ?> -<div id="order_history_block"> +<div id="order_history_block" class="edit-order-comments"> <?php if ($block->canAddComment()):?> - <div id="history_form"> - <div><?php echo __('Add Order Comments') ?></div> - <div> - <label for="history_status"><?php echo __('Status') ?></label> - <select name="history[status]" id="history_status"> - <?php foreach ($block->getStatuses() as $_code => $_label): ?> - <option value="<?php echo $_code ?>"<?php if ($_code == $block->getOrder()->getStatus()): ?> selected="selected"<?php endif; ?>><?php echo $_label ?></option> - <?php endforeach; ?> - </select> - </div> - <div> - <label for="history_comment"><?php echo __('Comment') ?></label> - <textarea name="history[comment]" rows="3" cols="5" id="history_comment"></textarea> - </div> - <div class="clearfix"> - <div class="order-history-comments-options"> - <?php if ($block->canSendCommentEmail()): ?> - <input name="history[is_customer_notified]" type="checkbox" id="history_notify" value="1" /><label for="history_notify"> <?php echo __('Notify Customer by Email') ?></label><br /> - <?php endif; ?> - <input name="history[is_visible_on_front]" type="checkbox" id="history_visible" value="1" /><label for="history_visible"> <?php echo __('Visible on Frontend') ?></label> + <div class="order-history-block" id="history_form"> + + <div class="admin__field"> + <label for="history_status" class="admin__field-label"><?php echo __('Status') ?></label> + <div class="admin__field-control"> + <select name="history[status]" id="history_status" class="admin__control-select"> + <?php foreach ($block->getStatuses() as $_code => $_label): ?> + <option value="<?php echo $_code ?>"<?php if ($_code == $block->getOrder()->getStatus()): ?> selected="selected"<?php endif; ?>><?php echo $_label ?></option> + <?php endforeach; ?> + </select> + </div> + </div> + + <div class="admin__field"> + <label for="history_comment" class="admin__field-label"> + <?php echo __('Comment') ?> + </label> + <div class="admin__field-control"> + <textarea name="history[comment]" + rows="3" + cols="5" + id="history_comment" + class="admin__control-textarea"></textarea> + </div> </div> - <div class="actions"> - <?php echo $block->getChildHtml('submit_button') ?> + + <div class="admin__field"> + <div class="order-history-comments-options"> + <div class="admin__field admin__field-option"> + <?php if ($block->canSendCommentEmail()): ?> + <input name="history[is_customer_notified]" + type="checkbox" + id="history_notify" + class="admin__control-checkbox" + value="1" /> + <label class="admin__field-label" for="history_notify"> + <?php echo __('Notify Customer by Email') ?> + </label> + <?php endif; ?> + </div> + + <div class="admin__field admin__field-option"> + <input name="history[is_visible_on_front]" + type="checkbox" + id="history_visible" + class="admin__control-checkbox" + value="1" /> + <label class="admin__field-label" for="history_visible"> + <?php echo __('Visible on Frontend') ?> + </label> + </div> + </div> + + <div class="order-history-comments-actions"> + <?php echo $block->getChildHtml('submit_button') ?> + </div> </div> </div> - </div> <?php endif;?> + <ul class="note-list"> <?php foreach ($block->getOrder()->getStatusHistoryCollection(true) as $_item): ?> - <li> + <li class="note-list-item"> <span class="note-list-date"><?php echo $block->formatDate($_item->getCreatedAtDate(), \IntlDateFormatter::MEDIUM) ?></span> <span class="note-list-time"><?php echo $block->formatTime($_item->getCreatedAtDate(), \IntlDateFormatter::MEDIUM) ?></span> <span class="note-list-status"><?php echo $_item->getStatusLabel() ?></span> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml index 62900a6f6bb0bb355529cb2b2414e02e5b9ad889..afd5fc24ba3e939735a13492154775d93265827b 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/info.phtml @@ -22,165 +22,158 @@ $orderStoreDate = $block->formatDate( ); ?> -<?php /* the opening and closing divs of these two clearfixes are in app\code\core\Mage\Adminhtml\view\adminhtml\sales\order\invoice\create\form.phtml */?> - -<div class="clearfix"> - - <div class="order-information"> - <?php /* Order Information */?> - <div class="fieldset-wrapper"> +<section class="admin__page-section order-view-account-information"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Order & Account Information') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-information"> + <?php /* Order Information */?> <?php if ($_order->getEmailSent()): $_email = __('the order confirmation email was sent'); else: $_email = __('the order confirmation email is not sent'); endif; ?> - <div class="fieldset-wrapper-title"> + <div class="admin__page-section-item-title"> <span class="title"> <?php if ($block->getNoUseOrderLink()): ?> - <?php echo __('Order # %1', $_order->getRealOrderId()) ?> (<span><?php echo $_email ?></span>) + <?php echo __('Order # %1', $_order->getRealOrderId()) ?> (<span><?php echo $_email ?></span>) <?php else: ?> - <a href="<?php echo $block->getViewUrl($_order->getId()) ?>"><?php echo __('Order # %1', $_order->getRealOrderId()) ?></a> - <span>(<?php echo $_email ?>)</span> + <a href="<?php echo $block->getViewUrl($_order->getId()) ?>"><?php echo __('Order # %1', $_order->getRealOrderId()) ?></a> + <span>(<?php echo $_email ?>)</span> <?php endif; ?> </span> </div> - <table class="data-table table-info"> + <div class="admin__page-section-item-content"> + <table class="data-table admin__table-secondary order-information-table"> <tr> <th><?php echo __('Order Date') ?></th> <td><?php echo $orderAdminDate ?></td> </tr> <?php if ($orderAdminDate != $orderStoreDate):?> - <tr> - <th><?php echo __( - 'Order Date (%1)', - $block->getCreatedAtStoreDate( - $_order->getStore(), - $_order->getCreatedAt() - )->getTimezone()->getName() - ) ?></th> - <td><?php echo $orderStoreDate ?></td> - </tr> + <tr> + <th><?php echo __( + 'Order Date (%1)', + $block->getCreatedAtStoreDate( + $_order->getStore(), + $_order->getCreatedAt() + )->getTimezone()->getName() + ) ?></th> + <td><?php echo $orderStoreDate ?></td> + </tr> <?php endif;?> <tr> <th><?php echo __('Order Status') ?></th> <td><span id="order_status"><?php echo $_order->getStatusLabel() ?></span></td> </tr> <?php if ($block->isSingleStoreMode() == false):?> - <tr> - <th><?php echo __('Purchased From') ?></th> - <td><?php echo $block->getOrderStoreName() ?></td> - </tr> + <tr> + <th><?php echo __('Purchased From') ?></th> + <td><?php echo $block->getOrderStoreName() ?></td> + </tr> <?php endif; ?> <?php if ($_order->getRelationChildId()): ?> - <tr> - <th><?php echo __('Link to the New Order') ?></th> - <td><a href="<?php echo $block->getViewUrl($_order->getRelationChildId()) ?>"> - <?php echo $_order->getRelationChildRealId() ?> - </a></td> - </tr> + <tr> + <th><?php echo __('Link to the New Order') ?></th> + <td><a href="<?php echo $block->getViewUrl($_order->getRelationChildId()) ?>"> + <?php echo $_order->getRelationChildRealId() ?> + </a></td> + </tr> <?php endif; ?> <?php if ($_order->getRelationParentId()): ?> - <tr> - <th><?php echo __('Link to the Previous Order') ?></th> - <td><a href="<?php echo $block->getViewUrl($_order->getRelationParentId()) ?>"> - <?php echo $_order->getRelationParentRealId() ?> - </a></td> - </tr> + <tr> + <th><?php echo __('Link to the Previous Order') ?></th> + <td><a href="<?php echo $block->getViewUrl($_order->getRelationParentId()) ?>"> + <?php echo $_order->getRelationParentRealId() ?> + </a></td> + </tr> <?php endif; ?> <?php if ($_order->getRemoteIp() && $block->shouldDisplayCustomerIp()): ?> - <tr> - <th><?php echo __('Placed from IP') ?></th> - <td><?php echo $_order->getRemoteIp(); echo($_order->getXForwardedFor()) ? ' (' . $block->escapeHtml($_order->getXForwardedFor()) . ')' : ''; ?></td> - </tr> + <tr> + <th><?php echo __('Placed from IP') ?></th> + <td><?php echo $_order->getRemoteIp(); echo($_order->getXForwardedFor()) ? ' (' . $block->escapeHtml($_order->getXForwardedFor()) . ')' : ''; ?></td> + </tr> <?php endif; ?> <?php if ($_order->getGlobalCurrencyCode() != $_order->getBaseCurrencyCode()): ?> - <tr> - <th><?php echo __('%1 / %2 rate:', $_order->getGlobalCurrencyCode(), $_order->getBaseCurrencyCode()) ?></th> - <td><?php echo $_order->getBaseToGlobalRate() ?></td> - </tr> + <tr> + <th><?php echo __('%1 / %2 rate:', $_order->getGlobalCurrencyCode(), $_order->getBaseCurrencyCode()) ?></th> + <td><?php echo $_order->getBaseToGlobalRate() ?></td> + </tr> <?php endif; ?> <?php if ($_order->getBaseCurrencyCode() != $_order->getOrderCurrencyCode()): ?> - <tr> - <th><?php echo __('%1 / %2 rate:', $_order->getOrderCurrencyCode(), $_order->getBaseCurrencyCode()) ?></th> - <th><?php echo $_order->getBaseToOrderRate() ?></th> - </tr> + <tr> + <th><?php echo __('%1 / %2 rate:', $_order->getOrderCurrencyCode(), $_order->getBaseCurrencyCode()) ?></th> + <th><?php echo $_order->getBaseToOrderRate() ?></th> + </tr> <?php endif; ?> </table> + </div> </div> - </div> - <div class="order-account-information"> - <?php /* Account Information */?> - <div class="admin__fieldset-wrapper"> - <div class="admin__fieldset-wrapper-title"> + <div class="admin__page-section-item order-account-information"> + <?php /* Account Information */?> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Account Information') ?></span> <div class="actions"><?php echo $block->getAccountEditLink()?></div> - <strong class="title"><?php echo __('Account Information') ?></strong> </div> - <table class="data-table table-info"> - <tr> - <th><?php echo __('Customer Name') ?></th> - <td> - <?php if ($_customerUrl = $block->getCustomerViewUrl()) : ?> - <a href="<?php echo $_customerUrl ?>" target="_blank"><strong><?php echo $block->escapeHtml($_order->getCustomerName()) ?></strong></a> - <?php else: ?> - <?php echo $block->escapeHtml($_order->getCustomerName()) ?> + <div class="admin__page-section-item-content"> + <table class="data-table admin__table-secondary order-account-information-table"> + <tr> + <th><?php echo __('Customer Name') ?></th> + <td> + <?php if ($_customerUrl = $block->getCustomerViewUrl()) : ?> + <a href="<?php echo $_customerUrl ?>" target="_blank"> + <span><?php echo $block->escapeHtml($_order->getCustomerName()) ?></span> + </a> + <?php else: ?> + <?php echo $block->escapeHtml($_order->getCustomerName()) ?> + <?php endif; ?> + </td> + </tr> + <tr> + <th><?php echo __('Email') ?></th> + <td><a href="mailto:<?php echo $_order->getCustomerEmail() ?>"><?php echo $_order->getCustomerEmail() ?></a></td> + </tr> + <?php if ($_groupName = $block->getCustomerGroupName()) : ?> + <tr> + <th><?php echo __('Customer Group') ?></th> + <td><?php echo $_groupName ?></td> + </tr> <?php endif; ?> - </td> - </tr> - <tr> - <th><?php echo __('Email') ?></th> - <td><a href="mailto:<?php echo $_order->getCustomerEmail() ?>"><?php echo $_order->getCustomerEmail() ?></a></td> - </tr> - <?php if ($_groupName = $block->getCustomerGroupName()) : ?> - <tr> - <th><?php echo __('Customer Group') ?></th> - <td><?php echo $_groupName ?></td> - </tr> - <?php endif; ?> - <?php foreach ($block->getCustomerAccountData() as $data):?> - <tr> - <th><?php echo $data['label'] ?></th> - <td><?php echo $data['value'] ?></td> - </tr> - <?php endforeach;?> - </table> + <?php foreach ($block->getCustomerAccountData() as $data):?> + <tr> + <th><?php echo $data['label'] ?></th> + <td><?php echo $data['value'] ?></td> + </tr> + <?php endforeach;?> + </table> + </div> </div> </div> +</section> -</div> - -<div class="clearfix"> - - <div class="order-billing-address"> - <?php /* Billing Address */?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <div class="actions"><?php echo $block->getAddressEditLink($_order->getBillingAddress()); ?></div> +<section class="admin__page-section order-addresses"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Address Information') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-billing-address"> + <?php /* Billing Address */?> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Billing Address') ?></span> + <div class="actions"><?php echo $block->getAddressEditLink($_order->getBillingAddress()); ?></div> </div> - <address><?php echo $block->getFormattedAddress($_order->getBillingAddress()); ?></address> + <address class="admin__page-section-item-content"><?php echo $block->getFormattedAddress($_order->getBillingAddress()); ?></address> </div> - </div> - - <?php if (!$block->getOrder()->getIsVirtual()): ?> - <div class="order-shipping-address"> - <?php /* Shipping Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <div class="actions"><?php echo $block->getAddressEditLink($_order->getShippingAddress()); ?></div> - <span class="title"><?php echo __('Shipping Address') ?></span> + <?php if (!$block->getOrder()->getIsVirtual()): ?> + <div class="admin__page-section-item order-shipping-address"> + <?php /* Shipping Address */ ?> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipping Address') ?></span> + <div class="actions"><?php echo $block->getAddressEditLink($_order->getShippingAddress()); ?></div> + </div> + <address class="admin__page-section-item-content"><?php echo $block->getFormattedAddress($_order->getShippingAddress()); ?></address> </div> - <address><?php echo $block->getFormattedAddress($_order->getShippingAddress()); ?></address> - </div> + <?php endif; ?> </div> -</div> - <?php endif; ?> - -<?php -/* - closing div of this opening div are in - app\code\Magento\Sales\view\adminhtml\order\invoice\view\form.phtml - or - app\code\Magento\Sales\view\adminhtml\order\view\tab\info.phtml -*/ -?> +</section> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/items.phtml index cb1c7006dd7518fb2a0531d62990980526fecfb9..7fc02861eff16e157e3a8842a84ec731e5ea43dc 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/items.phtml @@ -10,7 +10,7 @@ <?php $_order = $block->getOrder() ?> <div class="grid"> <div class="hor-scroll"> - <table class="data-table table-info"> + <table class="data-table admin__table-primary edit-order-table"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> @@ -25,13 +25,13 @@ <th class="col-total last"><span><?php echo __('Row Total') ?></span></th> </tr> </thead> - <?php $_items = $block->getItemsCollection() ?> + <?php $_items = $block->getItemsCollection();?> <?php $i = 0; foreach ($_items as $_item):?> <?php if ($_item->getParentItem()) { - continue; -} else { - $i++; -}?> + continue; + } else { + $i++; + }?> <tbody class="<?php echo $i%2 ? 'even' : 'odd' ?>"> <?php echo $block->getItemHtml($_item) ?> <?php echo $block->getItemExtraInfoHtml($_item) ?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/history.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/history.phtml index 7d9c3acc586e381767ded7f39b09af062bc4b1db..2e8eae106e6a9d0132978547405bb4c31cc787ac 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/history.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/history.phtml @@ -7,10 +7,10 @@ // @codingStandardsIgnoreFile ?> -<div class="fieldset-wrapper"> +<section class="admin__page-section edit-order-comments"> <ul class="note-list"> <?php foreach ($block->getFullHistory() as $_item): ?> - <li> + <li class="note-list-item"> <span class="note-list-date"><?php echo $block->getItemCreatedAt($_item) ?></span> <span class="note-list-time"><?php echo $block->getItemCreatedAt($_item, 'time') ?></span> <span class="note-list-status"><?php echo $block->getItemTitle($_item) ?></span> @@ -26,10 +26,26 @@ <?php endif; ?> </span> <?php endif; ?> - <?php if ($_comment = $block->getItemComment($_item)): ?> - <div class="note-list-comment"><?php echo $_comment ?></div> - <?php endif; ?> </li> <?php endforeach; ?> </ul> -</div> + <div class="edit-order-comments-block"> + <div class="edit-order-comments-block-title"> + <?php echo __('Notes for this Order') ?> + </div> + <?php foreach ($block->getFullHistory() as $_item): ?> + <?php if ($_comment = $block->getItemComment($_item)): ?> + <div class="comments-block-item"> + <div class="comments-block-item-comment"> + <?php echo $_comment ?> + </div> + <span class="comments-block-item-date-time"> + <?php echo __('Comment added') ?> + <?php echo $block->getItemCreatedAt($_item) ?> + <?php echo $block->getItemCreatedAt($_item, 'time') ?> + </span> + </div> + <?php endif; ?> + <?php endforeach; ?> + </div> +</section> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/info.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/info.phtml index a939192eba8c671d8e654beb40aa9495a7016cc8..b315a0053976c6dac80fba6dcb579ee1782cea58 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/info.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/tab/info.phtml @@ -17,60 +17,55 @@ <?php echo $block->getChildHtml('order_info') ?> <input type="hidden" name="order_id" value="<?php echo $_order->getId() ?>"/> -<?php if (!$_order->getIsVirtual()): ?> -<div class="clearfix"> -<?php endif; ?> - - <div class="order-payment-method<?php if ($_order->getIsVirtual()): ?> order-payment-method-virtual<?php endif; ?>"> - <?php /* Payment Method */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section order-view-billing-shipping"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Method') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-payment-method<?php if ($_order->getIsVirtual()): ?> order-payment-method-virtual<?php endif; ?>"> + <?php /* Payment Method */ ?> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Payment Information') ?></span> </div> - <div><?php echo $block->getPaymentHtml() ?></div> - <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> - <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> + <div class="admin__page-section-item-content"> + <div><?php echo $block->getPaymentHtml() ?></div> + <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> + <div class="order-payment-additional"><?php echo $block->getChildHtml('order_payment_additional'); ?></div> + </div> </div> + <?php echo $block->getChildHtml('order_shipping_view') ?> </div> - -<?php if ($_order->getIsVirtual()): ?> -</div><?php /* opening div is in app\code\Magento\Sales\view\adminhtml\order\view\info.phtml */ ?> -<?php endif; ?> - -<?php echo $block->getChildHtml('order_shipping_view') ?> - -<?php if (!$_order->getIsVirtual()): ?> -</div> -<?php endif; ?> +</section> <?php echo $block->getGiftOptionsHtml() ?> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Items Ordered') ?></span> </div> <?php echo $block->getItemsHtml() ?> -</div> +</section> -<div class="clearfix"> - <div class="order-comments-history"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Comments History') ?></span> +<section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Order Total') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-comments-history"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Notes for this Order') ?></span> </div> - <fieldset><?php echo $block->getChildHtml('order_history') ?></fieldset> + <?php echo $block->getChildHtml('order_history') ?> </div> - </div> - <div class="order-totals"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> + <div class="admin__page-section-item order-totals"> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Order Totals') ?></span> </div> <?php echo $block->getChildHtml('order_totals') ?> </div> </div> -</div> +</section> <?php echo $block->getChildHtml('popup_window');?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/transactions/detail.phtml b/app/code/Magento/Sales/view/adminhtml/templates/transactions/detail.phtml index 701a7c73a192f9f068b04129bac001f4e001f551..26d231c994314ff2524fe898bebc05817341829a 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/transactions/detail.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/transactions/detail.phtml @@ -8,12 +8,12 @@ ?> <div data-mage-init='{"floatingHeader": {}}' class="page-actions"><?php echo $block->getButtonsHtml() ?></div> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Transaction Data'); ?></span> </div> - <div id="log_details_fieldset" class="log-details"> - <table class="log-info data-table table-info"> + <div id="log_details_fieldset" class="admin__page-section-content log-details"> + <table class="log-info data-table admin__table-secondary"> <tbody> <tr> <th><?php echo __('Transaction ID'); ?></th> @@ -54,22 +54,22 @@ </tbody> </table> </div> -</div> +</section> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title""><?php echo __('Child Transactions'); ?></span> </div> - <div class="log-details-grid"> + <div class="admin__page-section-content log-details-grid"> <?php echo $block->getChildHtml('child_grid') ?> </div> -</div> +</section> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Transaction Details'); ?></span> </div> - <div class="log-details-grid"> + <div class="admin__page-section-content log-details-grid"> <?php echo $block->getChildHtml('detail_grid') ?> </div> -</div> +</section> diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js index 029a93e92456b0468571bb146a49c3aff2cc7ad0..f936da5c2516adf5ef34db62f334d811daf07adb 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js @@ -32,6 +32,7 @@ AdminOrder.prototype = { this.productPriceBase = {}; this.collectElementsValue = true; this.isOnlyVirtualProduct = false; + this.excludedPaymentMethods = []; Event.observe(window, 'load', (function(){ this.dataArea = new OrderFormArea('data', $(this.getAreaId('data')), this); this.itemsArea = Object.extend(new OrderFormArea('items', $(this.getAreaId('items')), this), { @@ -74,6 +75,13 @@ AdminOrder.prototype = { this.areasLoaded(); this.itemsArea.onLoad(); }).bind(this)); + + jQuery('#edit_form') + .on('submitOrder', function(){ + jQuery(this).trigger('realOrder'); + }) + .on('realOrder', this._realSubmit.bind(this)); + }, areasLoaded: function(){ @@ -94,6 +102,10 @@ AdminOrder.prototype = { this.addresses = addresses; }, + addExcludedPaymentMethod : function(method){ + this.excludedPaymentMethods.push(method); + }, + setCustomerId : function(id){ this.customerId = id; this.loadArea('header', true); @@ -327,6 +339,7 @@ AdminOrder.prototype = { }, switchPaymentMethod : function(method){ + jQuery('#edit_form').trigger('changePaymentMethod', [method]); this.setPaymentMethod(method); var data = {}; data['order[payment_method]'] = method; @@ -354,6 +367,7 @@ AdminOrder.prototype = { } if ($('payment_form_'+method)){ + jQuery('#' + this.getAreaId('billing_method')).trigger('contentUpdated'); this.paymentMethod = method; var form = 'payment_form_'+method; [form + '_before', form, form + '_after'].each(function(el) { @@ -394,6 +408,9 @@ AdminOrder.prototype = { return false; } } + if (this.isPaymentValidationAvailable() == false) { + return false; + } var data = {}; var fields = $('payment_form_' + currentMethod).select('input', 'select'); for(var i=0;i<fields.length;i++){ @@ -1037,15 +1054,30 @@ AdminOrder.prototype = { if (!params.form_key) { params.form_key = FORM_KEY; } - var data = this.serializeData('order-billing_method'); - if (data) { - data.each(function(value) { - params[value[0]] = value[1]; - }); + + if (this.isPaymentValidationAvailable()) { + var data = this.serializeData('order-billing_method'); + if (data) { + data.each(function(value) { + params[value[0]] = value[1]; + }); + } + } else { + params['payment[method]'] = this.paymentMethod; } return params; }, + /** + * Prevent from sending credit card information to server for some payment methods + * + * @returns {boolean} + */ + isPaymentValidationAvailable : function(){ + return ((typeof this.paymentMethod) == 'undefined' + || this.excludedPaymentMethods.indexOf(this.paymentMethod) == -1); + }, + serializeData : function(container){ var fields = $(container).select('input', 'select', 'textarea'); var data = Form.serializeElements(fields, true); @@ -1068,7 +1100,11 @@ AdminOrder.prototype = { submit : function() { - // Temporary solution will be replaced after refactoring order functionality + jQuery('#edit_form').trigger('processStart'); + jQuery('#edit_form').trigger('submitOrder'); + }, + + _realSubmit: function () { var disableAndSave = function() { disableElements('save'); jQuery('#edit_form').on('invalid-form.validate', function() { @@ -1308,4 +1344,4 @@ ControlButton.prototype = { } }; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json index 1ef5ba09232d018b9987d406fc67f2ef65af6209..6a4c27c399741ad9c8d74f2e95d2dc64a56b102a 100644 --- a/app/code/Magento/SalesRule/composer.json +++ b/app/code/Magento/SalesRule/composer.json @@ -3,26 +3,26 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-rule": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-payment": "0.74.0-beta6", - "magento/module-reports": "0.74.0-beta6", - "magento/module-catalog-rule": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-rule": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-payment": "0.74.0-beta7", + "magento/module-reports": "0.74.0-beta7", + "magento/module-catalog-rule": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/SalesSequence/composer.json b/app/code/Magento/SalesSequence/composer.json index f3c49c8f01143db554c75ed5abdcb14935ab4ef2..1f2fc3c267dbeeb9456e40b567f52d62b98531c2 100644 --- a/app/code/Magento/SalesSequence/composer.json +++ b/app/code/Magento/SalesSequence/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Search/Model/SearchEngine.php b/app/code/Magento/Search/Model/SearchEngine.php index c4d5c4787a17af5dbfd7f042da520650493642c3..f80e6bfd8796f2d6e2dae2901f27028964c97b6c 100644 --- a/app/code/Magento/Search/Model/SearchEngine.php +++ b/app/code/Magento/Search/Model/SearchEngine.php @@ -17,14 +17,21 @@ class SearchEngine implements SearchEngineInterface /** * @var AdapterInterface */ - protected $adapter; + private $adapter = null; + + /** + * Adapter factory + * + * @var AdapterFactory + */ + private $adapterFactory; /** * @param AdapterFactory $adapterFactory */ public function __construct(AdapterFactory $adapterFactory) { - $this->adapter = $adapterFactory->create(); + $this->adapterFactory = $adapterFactory; } /** @@ -32,6 +39,19 @@ class SearchEngine implements SearchEngineInterface */ public function search(RequestInterface $request) { - return $this->adapter->query($request); + return $this->getAdapter()->query($request); + } + + /** + * Get adapter + * + * @return AdapterInterface + */ + protected function getAdapter() + { + if ($this->adapter === null) { + $this->adapter = $this->adapterFactory->create(); + } + return $this->adapter; } } diff --git a/app/code/Magento/Search/composer.json b/app/code/Magento/Search/composer.json index 69bc52ccfec60bd0b606af29e9748896b6eefe32..841e086af01a4f23d31d3a89f134f5833f0921dc 100644 --- a/app/code/Magento/Search/composer.json +++ b/app/code/Magento/Search/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog-search": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-reports": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog-search": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-reports": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sendfriend/composer.json b/app/code/Magento/Sendfriend/composer.json index 7acd6e8fa3cece61f1c20f06067106d0b5691ba5..b17ea7f73d12b36993340f6884a195ee48417da0 100644 --- a/app/code/Magento/Sendfriend/composer.json +++ b/app/code/Magento/Sendfriend/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Shipping/Block/Adminhtml/View/Form.php b/app/code/Magento/Shipping/Block/Adminhtml/View/Form.php index 2f848e0a150c139f624847ddbdab1d9a89abd174..fa0d8aa70c9e118540e4532bb248db275bb2513c 100644 --- a/app/code/Magento/Shipping/Block/Adminhtml/View/Form.php +++ b/app/code/Magento/Shipping/Block/Adminhtml/View/Form.php @@ -79,7 +79,11 @@ class Form extends \Magento\Sales\Block\Adminhtml\Order\AbstractOrder return $this->getLayout()->createBlock( 'Magento\Backend\Block\Widget\Button' )->setData( - ['label' => __('Create Shipping Label...'), 'onclick' => 'packaging.showWindow();'] + [ + 'label' => __('Create Shipping Label...'), + 'onclick' => 'packaging.showWindow();', + 'class' => 'action-create-label' + ] )->toHtml(); } diff --git a/app/code/Magento/Shipping/Model/Order/Track.php b/app/code/Magento/Shipping/Model/Order/Track.php index 81b506a7d10d9a821df999357d74a3c914feb8a9..9763f2bdb6e49035dd9b5d16b0677b635b6dd39b 100644 --- a/app/code/Magento/Shipping/Model/Order/Track.php +++ b/app/code/Magento/Shipping/Model/Order/Track.php @@ -19,7 +19,6 @@ use Magento\Framework\Api\AttributeValueFactory; * @method string getTitle() * @method string getCarrierCode() * @method string getCreatedAt() - * @method \Magento\Sales\Model\Order\Shipment\Track setCreatedAt(string $value) * @method string getUpdatedAt() * @method \Magento\Sales\Api\Data\ShipmentTrackExtensionInterface getExtensionAttributes() */ diff --git a/app/code/Magento/Shipping/composer.json b/app/code/Magento/Shipping/composer.json index 54c613d4a0a95d2ab7d0a5eae1435dbfbffa9fff..9a1f9a4a0d0e500376b57cd48b4d615d3e2a6a3a 100644 --- a/app/code/Magento/Shipping/composer.json +++ b/app/code/Magento/Shipping/composer.json @@ -3,27 +3,27 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-contact": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-payment": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-contact": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-payment": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "ext-gd": "*", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-fedex": "0.74.0-beta6", - "magento/module-ups": "0.74.0-beta6" + "magento/module-fedex": "0.74.0-beta7", + "magento/module-ups": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_new.xml b/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_new.xml index 1c2aa23262486fb96b9eb05098cdb5e392596e24..de964564823074cc85563a2d677dd519eb1ff7f7 100644 --- a/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_new.xml +++ b/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_new.xml @@ -7,6 +7,7 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> <referenceContainer name="content"> <block class="Magento\Shipping\Block\Adminhtml\Create" name="sales_shipment_create"> <block class="Magento\Shipping\Block\Adminhtml\Create\Form" name="form" template="create/form.phtml"> diff --git a/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_view.xml b/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_view.xml index 8cdc5f8be0c8b547dd0b606358fb9b8ccb6ac2da..049654bf03a97ff760d1b1f2b80ac9fd48a05512 100644 --- a/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_view.xml +++ b/app/code/Magento/Shipping/view/adminhtml/layout/adminhtml_order_shipment_view.xml @@ -7,6 +7,7 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> + <referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" /> <!-- ToDo UI: remove this wrapper with old styles removal. The class name "admin__old" is for tests only, we shouldn't use it in any way --> <referenceContainer name="content"> <block class="Magento\Shipping\Block\Adminhtml\View" name="sales_shipment_view"> <block class="Magento\Shipping\Block\Adminhtml\View\Form" name="form" template="view/form.phtml"> diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/create/form.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/create/form.phtml index 28693ed0e0b947dccd7e43c878597d93d9ff29e0..46b4ab5ed56f691d3f7b0421d9e023ef3afaa9e0 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/create/form.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/create/form.phtml @@ -11,24 +11,27 @@ <?php echo $block->getBlockHtml('formkey')?> <?php $_order = $block->getShipment()->getOrder() ?> <?php echo $block->getChildHtml('order_info') ?> - <div class="clearfix"> - <div class="order-payment-method"> - <!--Billing Address--> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> + <div class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Method') ?></span> + </div> + <div class="admin__page-section-content"> + <div class="admin__page-section-item order-payment-method"> + <?php /* Billing Address */ ?> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Payment Information') ?></span> </div> - <div><?php echo $block->getPaymentHtml() ?></div> - <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> + <div class="admin__page-section-item-content"> + <div><?php echo $block->getPaymentHtml() ?></div> + <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> + </div> </div> - </div> - <div class="order-shipping-address"> - <!--Shipping Address--> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> + <div class="admin__page-section-item order-shipping-address"> + <?php /* Shipping Address */ ?> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Shipping Information') ?></span> </div> - <div class="shipping-description-wrapper"> + <div class="admin__page-section-item-content shipping-description-wrapper"> <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> <div class="shipping-description-content"> <?php echo __('Total Shipping Charges'); ?>: diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/create/items.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/create/items.phtml index b1544ff93ea9a2d15080bbea545aca5896c4ffcf..b2001f9ac88a4b9e8b47ccaa7b53f6b02ea4e128 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/create/items.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/create/items.phtml @@ -7,12 +7,13 @@ // @codingStandardsIgnoreFile ?> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> + +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Items to Ship') ?></span> </div> <div class="grid"> - <table cellspacing="0" class="data order-tables"> + <table class="data-table admin__table-primary order-shipment-table"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> @@ -34,44 +35,75 @@ <?php endforeach; ?> </table> </div> -</div> -<div class="clearfix"> - <div class="order-comments-history"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"><span class="title"><?php echo __('Shipment Comments') ?></span></div> - <fieldset> - <div id="order-history_form"> - <label class="normal" for="shipment_comment_text"><?php echo __('Shipment Comments') ?></label> - <textarea id="shipment_comment_text" name="shipment[comment_text]" rows="3" cols="5"><?php echo $block->getShipment()->getCommentText(); ?></textarea> +</section> + +<section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Shipment Total') ?></span> + </div> + <div class="admin__page-section-content order-comments-history"> + <div class="admin__page-section-item"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipment Comments') ?></span> + </div> + <div class="admin__page-section-item-content"> + <div id="order-history_form" class="admin__field"> + <label class="admin__field-label" + for="shipment_comment_text"> + <span><?php echo __('Comment Text') ?></span></label> + <textarea id="shipment_comment_text" + class="admin__control-textarea" + name="shipment[comment_text]" + rows="3" + cols="5"><?php echo $block->getShipment()->getCommentText(); ?></textarea> </div> - </fieldset> + </div> </div> </div> - <div class="order-totals"> - <div class="fieldset-wrapper"> - <?php if ($block->canCreateShippingLabel()): ?> - <div class="field choice field-create"> - <input id="create_shipping_label" name="shipment[create_shipping_label]" value="1" type="checkbox" - onclick="toggleCreateLabelCheckbox();"/> - <label class="normal" for="create_shipping_label"><?php echo __('Create Shipping Label') ?></label> - </div> - <?php endif ?> - <div class="field choice field-append"> - <input id="notify_customer" name="shipment[comment_customer_notify]" value="1" type="checkbox"/> - <label class="normal" for="notify_customer"><?php echo __('Append Comments') ?></label> + <div class="admin__page-section-item order-totals"> + <?php if ($block->canCreateShippingLabel()): ?> + <div class="field choice admin__field admin__field-option field-create"> + <input id="create_shipping_label" + class="admin__control-checkbox" + name="shipment[create_shipping_label]" + value="1" + type="checkbox" + onclick="toggleCreateLabelCheckbox();"/> + <label class="admin__field-label" + for="create_shipping_label"> + <span><?php echo __('Create Shipping Label') ?></span></label> </div> - <?php if ($block->canSendShipmentEmail()): ?> - <div class="field choice field-email"> - <input id="send_email" name="shipment[send_email]" value="1" type="checkbox"/> - <label class="normal" for="send_email"><?php echo __('Email Copy of Shipment') ?></label> - </div> - <?php endif; ?> - <div class="actions"> - <?php echo $block->getChildHtml('submit_button') ?> + <?php endif ?> + + <div class="field choice admin__field admin__field-option field-append"> + <input id="notify_customer" + class="admin__control-checkbox" + name="shipment[comment_customer_notify]" + value="1" + type="checkbox"/> + <label class="admin__field-label" + for="notify_customer"> + <span><?php echo __('Append Comments') ?></span></label> + </div> + + <?php if ($block->canSendShipmentEmail()): ?> + <div class="field choice admin__field admin__field-option field-email"> + <input id="send_email" + class="admin__control-checkbox" + name="shipment[send_email]" + value="1" + type="checkbox"/> + <label class="admin__field-label" + for="send_email"> + <span><?php echo __('Email Copy of Shipment') ?></span></label> </div> + <?php endif; ?> + + <div class="order-history-comments-actions actions"> + <?php echo $block->getChildHtml('submit_button') ?> </div> </div> -</div> +</section> <script> require([ "jquery", diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/create/items/renderer/default.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/create/items/renderer/default.phtml index 1acdd870909d1f38bb2f9783a6e5937e56d729c9..136612ef50ba971ede1a74e9123cc17845d02998 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/create/items/renderer/default.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/create/items/renderer/default.phtml @@ -13,7 +13,10 @@ <td class="col-ordered-qty"><?php echo $block->getColumnHtml($_item, 'qty') ?></td> <td class="col-qty <?php if ($block->isShipmentRegular()): ?>last<?php endif; ?>"> <?php if ($block->canShipPartiallyItem()): ?> - <input type="text" class="input-text qty-item" name="shipment[items][<?php echo $_item->getOrderItemId() ?>]" value="<?php echo $_item->getQty()*1 ?>" /> + <input type="text" + class="input-text admin__control-text qty-item" + name="shipment[items][<?php echo $_item->getOrderItemId() ?>]" + value="<?php echo $_item->getQty()*1 ?>" /> <?php else: ?> <?php echo $_item->getQty()*1 ?> <?php endif; ?> diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/order/Tracking/view.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/order/Tracking/view.phtml index 74a836156b05475a9b361d888800b3061f17e72a..1497b994f9acbc27c31272b23b45895a4f4a09cc 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/order/Tracking/view.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/order/Tracking/view.phtml @@ -8,49 +8,66 @@ ?> <?php /** @var $block Magento\Shipping\Block\Adminhtml\Order\Tracking\View */ ?> -<table cellspacing="0" class="data-table" id="shipment_tracking_info"> - <thead> - <tr class="headings"> - <th class="col-carrier"><?php echo __('Carrier') ?></th> - <th class="col-title"><?php echo __('Title') ?></th> - <th class="col-number"><?php echo __('Number') ?></th> - <th class="col-delete last"><?php echo __('Action') ?></th> - </tr> - </thead> - <tfoot> - <tr> - <td class="col-carrier"> - <select name="carrier" class="select" onchange="selectCarrier(this)"> - <?php foreach ($block->getCarriers() as $_code => $_name): ?> - <option value="<?php echo $_code ?>"><?php echo $block->escapeHtml($_name) ?></option> - <?php endforeach; ?> - </select> - </td> - <td class="col-title"><input class="input-text" type="text" id="tracking_title" name="title" value="" /></td> - <td class="col-number"><input class="input-text" type="text" id="tracking_number" name="number" value="" /></td> - <td class="col-delete last"><?php echo $block->getSaveButtonHtml() ?></td> - </tr> - </tfoot> -<?php if ($_tracks = $block->getShipment()->getAllTracks()): ?> - <tbody> - <?php $i = 0; foreach ($_tracks as $_track):$i++ ?> - <tr class="<?php echo($i%2 == 0) ? 'even' : 'odd' ?>"> - <td class="col-carrier"><?php echo $block->escapeHtml($block->getCarrierTitle($_track->getCarrierCode())) ?></td> - <td class="col-title"><?php echo $block->escapeHtml($_track->getTitle()) ?></td> - <td class="col-number"> - <?php if ($_track->isCustom()): ?> - <?php echo $block->escapeHtml($_track->getNumber()) ?> - <?php else: ?> - <a href="#" onclick="popWin('<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($_track) ?>','trackorder','width=800,height=600,resizable=yes,scrollbars=yes')"><?php echo $block->escapeHtml($_track->getNumber()) ?></a> - <div id="shipment_tracking_info_response_<?php echo $_track->getId() ?>"></div> - <?php endif; ?> - </td> - <td class="col-delete last"><a class="action- delete" href="#" onclick="deleteTrackingNumber('<?php echo $block->getRemoveUrl($_track) ?>'); return false;"><span><?php echo __('Delete') ?></span></a></td> - </tr> - <?php endforeach; ?> - </tbody> -<?php endif; ?> -</table> +<div class="admin__control-table-wrapper"> + <table class="data-table admin__control-table" id="shipment_tracking_info"> + <thead> + <tr class="headings"> + <th class="col-carrier"><?php echo __('Carrier') ?></th> + <th class="col-title"><?php echo __('Title') ?></th> + <th class="col-number"><?php echo __('Number') ?></th> + <th class="col-delete last"><?php echo __('Action') ?></th> + </tr> + </thead> + <tfoot> + <tr> + <td class="col-carrier"> + <select name="carrier" + class="select admin__control-select" + onchange="selectCarrier(this)"> + <?php foreach ($block->getCarriers() as $_code => $_name): ?> + <option value="<?php echo $_code ?>"><?php echo $block->escapeHtml($_name) ?></option> + <?php endforeach; ?> + </select> + </td> + <td class="col-title"> + <input class="input-text admin__control-text" + type="text" + id="tracking_title" + name="title" + value="" /> + </td> + <td class="col-number"> + <input class="input-text admin__control-text" + type="text" + id="tracking_number" + name="number" + value="" /> + </td> + <td class="col-delete last"><?php echo $block->getSaveButtonHtml() ?></td> + </tr> + </tfoot> + <?php if ($_tracks = $block->getShipment()->getAllTracks()): ?> + <tbody> + <?php $i = 0; foreach ($_tracks as $_track):$i++ ?> + <tr class="<?php echo($i%2 == 0) ? 'even' : 'odd' ?>"> + <td class="col-carrier"><?php echo $block->escapeHtml($block->getCarrierTitle($_track->getCarrierCode())) ?></td> + <td class="col-title"><?php echo $block->escapeHtml($_track->getTitle()) ?></td> + <td class="col-number"> + <?php if ($_track->isCustom()): ?> + <?php echo $block->escapeHtml($_track->getNumber()) ?> + <?php else: ?> + <a href="#" onclick="popWin('<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($_track) ?>','trackorder','width=800,height=600,resizable=yes,scrollbars=yes')"><?php echo $block->escapeHtml($_track->getNumber()) ?></a> + <div id="shipment_tracking_info_response_<?php echo $_track->getId() ?>"></div> + <?php endif; ?> + </td> + <td class="col-delete last"><a class="action-delete" href="#" onclick="deleteTrackingNumber('<?php echo $block->getRemoveUrl($_track) ?>'); return false;"><span><?php echo __('Delete') ?></span></a></td> + </tr> + <?php endforeach; ?> + </tbody> + <?php endif; ?> + </table> +</div> + <script> require(['prototype'], function(){ diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/grid.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/grid.phtml index aa8645eb6238e23547dc15df5e96c2fc388c9dcf..f696adb536c16ca453fb8090930cf2fe5e67f27f 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/grid.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/grid.phtml @@ -8,65 +8,88 @@ ?> <div class="grid"> - <table cellspacing="0" class="data-table"> - <thead> - <tr> - <th class="col-product no-link"><?php echo __('Product Name') ?></th> - <th class="col-weight no-link"><?php echo __('Weight') ?></th> - <th class="col-custom no-link" <?php echo $block->displayCustomsValue() ? '' : 'style="display: none;"' ?>> - <?php echo __('Customs Value') ?> - </th> - <th class="col-select no-link"> - <input type="checkbox" name="" onclick="packaging.checkAllItems(this);" class="checkbox" title="<?php echo __('Select All') ?>"> - </th> - <th class="col-qty no-link"><?php echo __('Qty Ordered') ?></th> - <th class="col-qty-edit no-link last"><?php echo __('Qty') ?></th> - </tr> - </thead> + <div class="hor-scroll"> + <table class="data-table admin__table-primary"> + <thead> + <tr> + <th class="col-product no-link"><?php echo __('Product Name') ?></th> + <th class="col-weight no-link"><?php echo __('Weight') ?></th> + <th class="col-custom no-link" <?php echo $block->displayCustomsValue() ? '' : 'style="display: none;"' ?>> + <?php echo __('Customs Value') ?> + </th> + <th class="col-select no-link"> + <div class="admin__field admin__field-option"> + <input type="checkbox" + name="" + onclick="packaging.checkAllItems(this);" + class="checkbox admin__control-checkbox" + title="<?php echo __('Select All') ?>"> + <label class="admin__field-label"></label> + </div> + </th> + <th class="col-qty no-link"><?php echo __('Qty Ordered') ?></th> + <th class="col-qty-edit no-link last"><?php echo __('Qty') ?></th> + </tr> + </thead> - <tbody> - <?php foreach ($block->getCollection() as $item): ?> - <?php $_order = $block->getShipment()->getOrder() ?> - <?php $_orderItem = $_order->getItemById($item->getOrderItemId()); ?> - <?php if ($item->getIsVirtual() - || ($_orderItem->isShipSeparately() && !($_orderItem->getParentItemId() || $_orderItem->getParentItem())) - || (!$_orderItem->isShipSeparately() && ($_orderItem->getParentItemId() || $_orderItem->getParentItem()))): ?> - <?php continue; ?> + <tbody> + <?php foreach ($block->getCollection() as $item): ?> + <?php $_order = $block->getShipment()->getOrder() ?> + <?php $_orderItem = $_order->getItemById($item->getOrderItemId()); ?> + <?php if ($item->getIsVirtual() + || ($_orderItem->isShipSeparately() && !($_orderItem->getParentItemId() || $_orderItem->getParentItem())) + || (!$_orderItem->isShipSeparately() && ($_orderItem->getParentItemId() || $_orderItem->getParentItem()))): ?> + <?php continue; ?> <?php endif; ?> - <tr title="#" id="" class=""> - <td class="col-product name"> - <?php echo $item->getName(); ?> - </td> - <td class="col-weight weight "> - <?php echo $item->getWeight(); ?> - </td> - <?php - if ($block->displayCustomsValue()) { - $customsValueDisplay = ''; - $customsValueValidation = ' validate-zero-or-greater '; - } else { - $customsValueDisplay = ' style="display: none;" '; - $customsValueValidation = ''; - } - ?> - <td <?php echo $customsValueDisplay ?>> - <input type="text" name="customs_value" class="input-text <?php echo $customsValueValidation ?>" value="<?php echo $block->formatPrice($item->getPrice()); ?>" size="10" onblur="packaging.recalcContainerWeightAndCustomsValue(this);"> - </td> - <td class="col-select"> - <input type="checkbox" name="" value="<?php echo $item->getId() ? $item->getId() : $item->getOrderItemId(); ?>" class="checkbox"> - </td> - <td class="col-qty"> - <?php echo $item->getOrderItem()->getQtyOrdered()*1; ?> - </td> - <td class="col-qty-edit last"> - <input type="hidden" name="price" value="<?php echo $item->getPrice(); ?>"> - <input type="text" name="qty" value="<?php echo $item->getQty()*1; ?>" class="input-text qty<?php if ($item->getOrderItem()->getIsQtyDecimal()): ?> qty-decimal<?php endif ?>"> - <button type="button" class="action- delete icon-btn" onclick="packaging.deleteItem(this);" style="display:none;"> - <span><?php echo __('Delete') ?></span> - </button> - </td> - </tr> + <tr title="#" id="" class=""> + <td class="col-product name"> + <?php echo $item->getName(); ?> + </td> + <td class="col-weight weight "> + <?php echo $item->getWeight(); ?> + </td> + <?php + if ($block->displayCustomsValue()) { + $customsValueDisplay = ''; + $customsValueValidation = ' validate-zero-or-greater '; + } else { + $customsValueDisplay = ' style="display: none;" '; + $customsValueValidation = ''; + } + ?> + <td <?php echo $customsValueDisplay ?>> + <input type="text" + name="customs_value" + class="input-text admin__control-text <?php echo $customsValueValidation ?>" + value="<?php echo $block->formatPrice($item->getPrice()); ?>" + size="10" + onblur="packaging.recalcContainerWeightAndCustomsValue(this);"> + </td> + <td class="col-select"> + <div class="admin__field admin__field-option"> + <input type="checkbox" + name="" + value="<?php echo $item->getId() ? $item->getId() : $item->getOrderItemId(); ?>" + class="checkbox admin__control-checkbox"> + <label class="admin__field-label"></label> + </div> + </td> + <td class="col-qty"> + <?php echo $item->getOrderItem()->getQtyOrdered()*1; ?> + </td> + <td class="col-qty-edit last"> + <input type="hidden" name="price" value="<?php echo $item->getPrice(); ?>"> + <input type="text" + name="qty" + value="<?php echo $item->getQty()*1; ?>" + class="input-text admin__control-text qty<?php if ($item->getOrderItem()->getIsQtyDecimal()): ?> qty-decimal<?php endif ?>"> + <button type="button" class="action-delete delete icon-btn" onclick="packaging.deleteItem(this);" style="display:none;"> + <span><?php echo __('Delete') ?></span> + </button> + </td> + </tr> <?php endforeach; ?> - </tbody> - </table> + </tbody> + </table> + </div> </div> diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/popup.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/popup.phtml index 7876d0ae1b8754efad94938cd984a7e90169f560..359dde8e59b198aa5be1907d9839c31b64166d20 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/popup.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/order/packaging/popup.phtml @@ -53,149 +53,186 @@ require([ <div class="popup-window-wrapper"> <div class="popup-window-title"> <div class="actions"> - <button type="button" class="action-add AddPackageBtn" onclick="packaging.newPackage();"> + <button type="button" class="action-add action-secondary AddPackageBtn" onclick="packaging.newPackage();"> <span><?php echo __('Add Package') ?></span> </button> </div> <span class="title"><?php echo __('Create Packages') ?></span> </div> <div class="packaging-content popup-window-content"> - <div class="messages" style="display:none;"></div> + <div class="message message-warning" style="display: none"></div> <div id="package_template" style="display:none;"> <div class="package-number popup-fieldset-title"> - <div class="title"><?php echo __('Package') ?><span></span></div> + <div class="title"> + <?php echo __('Package') ?> + <span></span> + </div> + </div> + <div class="admin__control-table-wrapper"> + <table class="data-table admin__control-table"> + <thead> + <th class="col-type"><?php echo __('Type') ?></th> + <?php if ($girthEnabled == 1): ?> + <th class="col-size"><?php echo __('Size') ?></th> + <th class="col-girth"><?php echo __('Girth') ?></th> + <th> </th> + <?php endif; ?> + <th class="col-custom" <?php echo $block->displayCustomsValue() ? '' : 'style="display: none;"' ?>> + <?php echo __('Customs Value') ?> + </th> + <th class="col-total-weight"><?php echo __('Total Weight') ?></th> + <th class="col-length"><?php echo __('Length') ?></th> + <th class="col-width"><?php echo __('Width') ?></th> + <th class="col-height"><?php echo __('Height') ?></th> + <th> </th> + <?php if ($block->getDeliveryConfirmationTypes()): ?> + <th class="col-signature"><?php echo __('Signature Confirmation') ?></th> + <?php endif; ?> + <th class="col-actions"> </th> + </thead> + <tbody> + <td class="col-type"> + <?php $containers = $block->getContainers(); ?> + <select name="package_container" + onchange="packaging.changeContainerType(this);packaging.checkSizeAndGirthParameter(this, <?php echo $girthEnabled ?>);" + <?php if (empty($containers)):?> + title="<?php echo __('USPS domestic shipments don\'t use package types.') ?>" + disabled="" + class="admin__control-select disabled" + <?php else: ?> + class="admin__control-select" + <?php endif; ?>> + <?php foreach ($block->getContainers() as $key => $value): ?> + <option value="<?php echo $key ?>" > + <?php echo $value ?> + </option> + <?php endforeach; ?> + </select> + </td> + <?php if ($girthEnabled == 1 && !empty($sizeSource)): ?> + <td> + <select name="package_size" + class="admin__control-select" + onchange="packaging.checkSizeAndGirthParameter(this, <?php echo $girthEnabled ?>);"> + <?php foreach ($sizeSource as $key => $value): ?> + <option value="<?php echo $sizeSource[$key]['value'] ?>"> + <?php echo $sizeSource[$key]['label'] ?> + </option> + <?php endforeach; ?> + </select> + </td> + <td> + <input type="text" + class="input-text admin__control-text validate-greater-than-zero" + name="container_girth" /> + </td> + <td> + <select name="container_girth_dimension_units" + class="options-units-dimensions measures admin__control-select" + onchange="packaging.changeMeasures(this);"> + <option value="<?php echo Zend_Measure_Length::INCH ?>" selected="selected" ><?php echo __('in') ?></option> + <option value="<?php echo Zend_Measure_Length::CENTIMETER ?>" ><?php echo __('cm') ?></option> + </select> + </td> + <?php endif; ?> + <?php + if ($block->displayCustomsValue()) { + $customsValueDisplay = ''; + $customsValueValidation = ' validate-zero-or-greater '; + } else { + $customsValueDisplay = ' style="display: none;" '; + $customsValueValidation = ''; + } + ?> + <td class="col-custom" <?php echo $customsValueDisplay ?>> + <input type="text" + class="customs-value input-text admin__control-text <?php echo $customsValueValidation ?>" + name="package_customs_value" /> + <span class="customs-value-currency">[<?php echo $block->getCustomValueCurrencyCode(); ?>]</span> + </td> + <td class="col-total-weight"> + <input type="text" + class="options-weight input-text admin__control-text required-entry validate-greater-than-zero" + name="container_weight" /> + <select name="container_weight_units" + class="options-units-weight measures admin__control-select" + onchange="packaging.changeMeasures(this);"> + <option value="<?php echo Zend_Measure_Weight::POUND ?>" selected="selected" ><?php echo __('lb') ?></option> + <option value="<?php echo Zend_Measure_Weight::KILOGRAM ?>" ><?php echo __('kg') ?></option> + </select> + </td> + <td class="col-length"> + <input type="text" + class="input-text admin__control-text validate-greater-than-zero" + name="container_length" /> + </td> + <td class="col-width"> + <input type="text" + class="input-text admin__control-text validate-greater-than-zero" + name="container_width" /> + </td> + <td class="col-height"> + <input type="text" + class="input-text admin__control-text validate-greater-than-zero" + name="container_height" /> + </td> + <td class="col-measure"> + <select name="container_dimension_units" + class="options-units-dimensions measures admin__control-select" + onchange="packaging.changeMeasures(this);"> + <option value="<?php echo Zend_Measure_Length::INCH ?>" selected="selected" ><?php echo __('in') ?></option> + <option value="<?php echo Zend_Measure_Length::CENTIMETER ?>" ><?php echo __('cm') ?></option> + </select> + </td> + <?php if ($block->getDeliveryConfirmationTypes()): ?> + <td> + <select name="delivery_confirmation_types" class="admin__control-select"> + <?php foreach ($block->getDeliveryConfirmationTypes() as $key => $value): ?> + <option value="<?php echo $key ?>" > + <?php echo $value ?> + </option> + <?php endforeach; ?> + </select> + </td> + <?php endif; ?> + <td class="col-actions"> + <button type="button" class="action-add AddItemsBtn" onclick="packaging.getItemsForPack(this);"> + <span><?php echo __('Add') ?></span> + </button> + <button type="button" class="action-delete DeletePackageBtn" onclick="packaging.deletePackage(this);"> + <span><?php echo __('Delete Package') ?></span> + </button> + </td> + </tbody> + </table> </div> - <table class="data-table" cellspacing="0"> - <thead> - <th class="col-type"><?php echo __('Type') ?></th> - <?php if ($girthEnabled == 1): ?> - <th class="col-size"><?php echo __('Size') ?></th> - <th class="col-girth"><?php echo __('Girth') ?></th> - <th> </th> - <?php endif; ?> - <th class="col-custom" <?php echo $block->displayCustomsValue() ? '' : 'style="display: none;"' ?>> - <?php echo __('Customs Value') ?> - </th> - <th class="col-total-weight"><?php echo __('Total Weight') ?></th> - <th class="col-length"><?php echo __('Length') ?></th> - <th class="col-width"><?php echo __('Width') ?></th> - <th class="col-height"><?php echo __('Height') ?></th> - <th> </th> - <?php if ($block->getDeliveryConfirmationTypes()): ?> - <th class="col-signature"><?php echo __('Signature Confirmation') ?></th> - <?php endif; ?> - <th class="col-actions"> </th> - </thead> - <tbody> - <td class="col-type"> - <?php $containers = $block->getContainers(); ?> - <select name="package_container" onchange="packaging.changeContainerType(this);packaging.checkSizeAndGirthParameter(this, <?php echo $girthEnabled ?>);"<?php if (empty($containers)):?> - title="<?php echo __('USPS domestic shipments don\'t use package types.') ?>" - disabled="" class="disabled" - <?php endif; ?>> - <?php foreach ($block->getContainers() as $key => $value): ?> - <option value="<?php echo $key ?>" > - <?php echo $value ?> - </option> - <?php endforeach; ?> - </select> - </td> - <?php if ($girthEnabled == 1 && !empty($sizeSource)): ?> - <td> - <select name="package_size" onchange="packaging.checkSizeAndGirthParameter(this, <?php echo $girthEnabled ?>);"> - <?php foreach ($sizeSource as $key => $value): ?> - <option value="<?php echo $sizeSource[$key]['value'] ?>"> - <?php echo $sizeSource[$key]['label'] ?> - </option> - <?php endforeach; ?> - </select> - </td> - <td><input type="text" class="input-text validate-greater-than-zero" name="container_girth" /></td> - <td> - <select name="container_girth_dimension_units" class="options-units-dimensions measures" onchange="packaging.changeMeasures(this);"> - <option value="<?php echo Zend_Measure_Length::INCH ?>" selected="selected" ><?php echo __('in') ?></option> - <option value="<?php echo Zend_Measure_Length::CENTIMETER ?>" ><?php echo __('cm') ?></option> - </select> - </td> - <?php endif; ?> - <?php - if ($block->displayCustomsValue()) { - $customsValueDisplay = ''; - $customsValueValidation = ' validate-zero-or-greater '; - } else { - $customsValueDisplay = ' style="display: none;" '; - $customsValueValidation = ''; - } - ?> - <td class="col-custom" <?php echo $customsValueDisplay ?>> - <input type="text" class="customs-value input-text <?php echo $customsValueValidation ?>" name="package_customs_value" /> - <span class="customs-value-currency">[<?php echo $block->getCustomValueCurrencyCode(); ?>]</span> - </td> - <td class="col-total-weight"> - <input type="text" class="options-weight input-text required-entry validate-greater-than-zero" name="container_weight" /> - <select name="container_weight_units" class="options-units-weight measures" onchange="packaging.changeMeasures(this);"> - <option value="<?php echo Zend_Measure_Weight::POUND ?>" selected="selected" ><?php echo __('lb') ?></option> - <option value="<?php echo Zend_Measure_Weight::KILOGRAM ?>" ><?php echo __('kg') ?></option> - </select> - </td> - <td class="col-length"> - <input type="text" class="input-text validate-greater-than-zero" name="container_length" /> - </td> - <td class="col-width"> - <input type="text" class="input-text validate-greater-than-zero" name="container_width" /> - </td> - <td class="col-height"> - <input type="text" class="input-text validate-greater-than-zero" name="container_height" /> - </td> - <td class="col-measure"> - <select name="container_dimension_units" class="options-units-dimensions measures" onchange="packaging.changeMeasures(this);"> - <option value="<?php echo Zend_Measure_Length::INCH ?>" selected="selected" ><?php echo __('in') ?></option> - <option value="<?php echo Zend_Measure_Length::CENTIMETER ?>" ><?php echo __('cm') ?></option> - </select> - </td> - <?php if ($block->getDeliveryConfirmationTypes()): ?> - <td> - <select name="delivery_confirmation_types"> - <?php foreach ($block->getDeliveryConfirmationTypes() as $key => $value): ?> - <option value="<?php echo $key ?>" > - <?php echo $value ?> - </option> - <?php endforeach; ?> - </select> - </td> - <?php endif; ?> - <td class="col-actions"> - <button type="button" class="action-add AddItemsBtn" onclick="packaging.getItemsForPack(this);"> - <span><?php echo __('Add Products') ?></span> - </button> - <button type="button" class="action-delete DeletePackageBtn" onclick="packaging.deletePackage(this);"> - <span><?php echo __('Delete Package') ?></span> - </button> - </td> - </tbody> - </table> <?php if ($block->getContentTypes()): ?> - <table class="package-options package-options-contents data-table" cellspacing="0"> - <thead> - <th><?php echo __('Contents') ?></th> - <th><?php echo __('Explanation') ?></th> - </thead> - <tbody> - <td> - <select name="content_type" onchange="packaging.changeContentTypes(this);"> - <?php foreach ($block->getContentTypes() as $key => $value): ?> - <option value="<?php echo $key ?>" > - <?php echo $value ?> - </option> - <?php endforeach; ?> - </select> - </td> - <td> - <input name="content_type_other" type="text" class="input-text options-content-type disabled" disabled="disabled" /> - </td> - </tbody> - </table> + <table class="package-options package-options-contents data-table" cellspacing="0"> + <thead> + <th><?php echo __('Contents') ?></th> + <th><?php echo __('Explanation') ?></th> + </thead> + <tbody> + <td> + <select name="content_type" + class="admin__control-select" + onchange="packaging.changeContentTypes(this);"> + <?php foreach ($block->getContentTypes() as $key => $value): ?> + <option value="<?php echo $key ?>" > + <?php echo $value ?> + </option> + <?php endforeach; ?> + </select> + </td> + <td> + <input name="content_type_other" + type="text" + class="input-text admin__control-text options-content-type disabled" + disabled="disabled" /> + </td> + </tbody> + </table> <?php endif; ?> <div class="package-add-products"> <div class="package_prapare" style="display:none"> @@ -214,7 +251,11 @@ require([ <div id="packages_content"></div> </div> <div class="popup-window-buttons-set"> - <button type="button" class="action-ok disabled SavePackagesBtn" disabled="disabled" onclick="packaging.confirmPackaging();" title="<?php echo __('Products should be added to package(s)')?>"> + <button type="button" + class="action-save action-secondary disabled SavePackagesBtn" + disabled="disabled" + onclick="packaging.confirmPackaging();" + title="<?php echo __('Products should be added to package(s)')?>"> <span><?php echo __('OK') ?></span> </button> <button type="button" class="action-close" onclick="packaging.cancelPackaging();"> diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/order/tracking.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/order/tracking.phtml index bf0b417d2bd8adcde2c95cb38c2db26c8be01a5d..cb8d042a65f47a3d149ac8c99efc87c4ab6d1872 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/order/tracking.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/order/tracking.phtml @@ -64,34 +64,40 @@ require(['prototype'], function(){ <script id="track_row_template" type="text/x-magento-template"> <tr> <td class="col-carrier"> - <select name="tracking[<%- data.index %>][carrier_code]" id="trackingC<%- data.index %>" class="select carrier" disabled="disabled"> + <select name="tracking[<%- data.index %>][carrier_code]" + id="trackingC<%- data.index %>" + class="select admin__control-select carrier" + disabled="disabled"> <?php foreach ($block->getCarriers() as $_code => $_name): ?> <option value="<?php echo $_code ?>"><?php echo $block->escapeHtml($_name) ?></option> <?php endforeach; ?> </select> </td> - <td class="col-title"><input class="input-text number-title" type="text" name="tracking[<%- data.index %>][title]" id="trackingT<%- data.index %>" value="" disabled="disabled" /></td> - <td class="col-number"><input class="input-text required-entry" type="text" name="tracking[<%- data.index %>][number]" id="trackingN<%- data.index %>" value="" disabled="disabled" /></td> - <td class="col-delete last"><a href="#" class="action- delete" onclick="trackingControl.deleteRow(event);return false"><span><?php echo __('Delete') ?></span></a></td> + <td class="col-title"><input class="input-text admin__control-text number-title" type="text" name="tracking[<%- data.index %>][title]" id="trackingT<%- data.index %>" value="" disabled="disabled" /></td> + <td class="col-number"><input class="input-text admin__control-text required-entry" type="text" name="tracking[<%- data.index %>][number]" id="trackingN<%- data.index %>" value="" disabled="disabled" /></td> + <td class="col-delete"><a href="#" class="action-delete" onclick="trackingControl.deleteRow(event);return false"><span><?php echo __('Delete') ?></span></a></td> </tr> </script> -<table cellspacing="0" class="data-table" id="tracking_numbers_table"> - <thead> - <tr class="headings"> - <th class="col-carrier"><?php echo __('Carrier') ?></th> - <th class="col-title"><?php echo __('Title') ?></th> - <th class="col-number"><?php echo __('Number') ?></th> - <th class="col-delete last"><?php echo __('Action') ?></th> - </tr> - </thead> - <tfoot> - <tr> - <td colspan="4" class="last col-actions-add"><?php echo $block->getChildHtml('add_button') ?></td> - </tr> - </tfoot> - <tbody id="track_row_container"> - </tbody> -</table> + +<div class="admin__control-table-wrapper"> + <table class="data-table admin__control-table" id="tracking_numbers_table"> + <thead> + <tr class="headings"> + <th class="col-carrier"><?php echo __('Carrier') ?></th> + <th class="col-title"><?php echo __('Title') ?></th> + <th class="col-number"><?php echo __('Number') ?></th> + <th class="col-delete"><?php echo __('Action') ?></th> + </tr> + </thead> + <tfoot> + <tr> + <td colspan="4" class="col-actions-add"><?php echo $block->getChildHtml('add_button') ?></td> + </tr> + </tfoot> + <tbody id="track_row_container"> + </tbody> + </table> +</div> <script> require([ 'mage/template', diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/order/view/info.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/order/view/info.phtml index e527501f2e5414cfb1001445b8b43d9cfbe3f544..53ce09410322557fa80728cfe384be1d82f958ef 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/order/view/info.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/order/view/info.phtml @@ -10,33 +10,32 @@ <?php /** @var $block \Magento\Shipping\Block\Adminhtml\View */ ?> <?php $order = $block->getOrder() ?> <?php if ($order->getIsVirtual()) : return '';endif; ?> -<div class="order-shipping-method"> - <!--Shipping Method--> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> - <span class="title"><?php echo __('Shipping & Handling Information') ?></span> - </div> - <div class="shipping-description-wrapper"> - <?php if ($order->getTracksCollection()->count()) : ?> - <p><a href="#" id="linkId" onclick="popWin('<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($order) ?>','trackorder','width=800,height=600,resizable=yes,scrollbars=yes')" title="<?php echo __('Track Order') ?>"><?php echo __('Track Order') ?></a></p> - <?php endif; ?> - <?php if ($order->getShippingDescription()): ?> - <strong><?php echo $block->escapeHtml($order->getShippingDescription()) ?></strong> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> - <?php $_excl = $block->displayShippingPriceInclTax($order); ?> - <?php else: ?> - <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> - <?php endif; ?> - <?php $_incl = $block->displayShippingPriceInclTax($order); ?> +<?php /* Shipping Method */ ?> +<div class="admin__page-section-item order-shipping-method"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipping & Handling Information') ?></span> + </div> + <div class="admin__page-section-item-content"> + <?php if ($order->getTracksCollection()->count()) : ?> + <p><a href="#" id="linkId" onclick="popWin('<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($order) ?>','trackorder','width=800,height=600,resizable=yes,scrollbars=yes')" title="<?php echo __('Track Order') ?>"><?php echo __('Track Order') ?></a></p> + <?php endif; ?> + <?php if ($order->getShippingDescription()): ?> + <strong><?php echo $block->escapeHtml($order->getShippingDescription()) ?></strong> - <?php echo $_excl; ?> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> - (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) - <?php endif; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> + <?php $_excl = $block->displayShippingPriceInclTax($order); ?> <?php else: ?> - <?php echo __('No shipping information available'); ?> + <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> + <?php endif; ?> + <?php $_incl = $block->displayShippingPriceInclTax($order); ?> + + <?php echo $_excl; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> + (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) <?php endif; ?> - </div> + <?php else: ?> + <?php echo __('No shipping information available'); ?> + <?php endif; ?> </div> </div> diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/view/form.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/view/form.phtml index 7a777c90d468a360a1279cdbccc9f333e8d4d4f4..16dc0556a52a2bdad4ad53a86293f6e842737f38 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/view/form.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/view/form.phtml @@ -9,94 +9,110 @@ ?> <?php $_order = $block->getShipment()->getOrder() ?> <?php echo $block->getChildHtml('order_info') ?> -<div class="clearfix"> - <div class="order-payment-method"> +<section class="admin__page-section order-shipment-billing-shipping"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Payment & Shipping Method') ?></span> + </div> + <div class="admin__page-section-content"> + <?php /* Billing Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> + <div class="admin__page-section-item order-payment-method"> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Payment Information') ?></span> </div> - <div><?php echo $block->getChildHtml('order_payment') ?></div> - <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> + <div class="admin__page-section-item-content"> + <div><?php echo $block->getChildHtml('order_payment') ?></div> + <div class="order-payment-currency"><?php echo __('The order was placed using %1.', $_order->getOrderCurrencyCode()) ?></div> + </div> </div> - </div> - <div class="order-shipping-address"> + <?php /* Shipping Address */ ?> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> + <div class="admin__page-section-item order-shipping-address"> + <div class="admin__page-section-item-title"> <span class="title"><?php echo __('Shipping and Tracking Information') ?></span> </div> - <div class="shipping-description-wrapper"> - <?php if ($block->getShipment()->getTracksCollection()->count()): ?> - <p> - <a href="#" id="linkId" onclick="popWin('<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($block->getShipment()) ?>','trackshipment','width=800,height=600,resizable=yes,scrollbars=yes')" title="<?php echo __('Track this shipment') ?>"><?php echo __('Track this shipment') ?></a> - </p> - <?php endif; ?> - <div class="shipping-description-title"><?php echo $block->escapeHtml($_order->getShippingDescription()) ?></div> - <?php echo __('Total Shipping Charges'); ?>: + <div class="admin__page-section-item-content"> + <div class="shipping-description-wrapper"> + <?php if ($block->getShipment()->getTracksCollection()->count()): ?> + <p> + <a href="#" id="linkId" onclick="popWin('<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($block->getShipment()) ?>','trackshipment','width=800,height=600,resizable=yes,scrollbars=yes')" title="<?php echo __('Track this shipment') ?>"><?php echo __('Track this shipment') ?></a> + </p> + <?php endif; ?> + <div class="shipping-description-title"> + <?php echo $block->escapeHtml($_order->getShippingDescription()) ?> + </div> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> - <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> - <?php else: ?> - <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> - <?php endif; ?> - <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> + <?php echo __('Total Shipping Charges'); ?>: - <?php echo $_excl; ?> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> - (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) - <?php endif; ?> - </div> - <?php if ($block->canCreateShippingLabel()): ?> - <p> - <?php echo $block->getCreateLabelButton()?> - <?php if ($block->getShipment()->getShippingLabel()): ?> - <?php echo $block->getPrintLabelButton() ?> - <?php endif ?> - <?php if ($block->getShipment()->getPackages()): ?> - <?php echo $block->getShowPackagesButton() ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingPriceIncludingTax()): ?> + <?php $_excl = $block->displayShippingPriceInclTax($_order); ?> + <?php else: ?> + <?php $_excl = $block->displayPriceAttribute('shipping_amount', false, ' '); ?> + <?php endif; ?> + <?php $_incl = $block->displayShippingPriceInclTax($_order); ?> + + <?php echo $_excl; ?> + <?php if ($this->helper('Magento\Tax\Helper\Data')->displayShippingBothPrices() && $_incl != $_excl): ?> + (<?php echo __('Incl. Tax'); ?> <?php echo $_incl; ?>) + <?php endif; ?> + </div> + <?php if ($block->canCreateShippingLabel()): ?> + <p> + <?php echo $block->getCreateLabelButton()?> + <?php if ($block->getShipment()->getShippingLabel()): ?> + <?php echo $block->getPrintLabelButton() ?> + <?php endif ?> + <?php if ($block->getShipment()->getPackages()): ?> + <?php echo $block->getShowPackagesButton() ?> + <?php endif ?> + </p> <?php endif ?> - </p> - <?php endif ?> - <div><?php echo $block->getChildHtml('shipment_tracking') ?></div> - <?php echo $block->getChildHtml('shipment_packaging') ?> - <script> -require([ - 'prototype' -], function(){ + <?php echo $block->getChildHtml('shipment_tracking') ?> - setTimeout(function(){ - packaging.setConfirmPackagingCallback(function(){ - packaging.sendCreateLabelRequest(); - }); - packaging.setLabelCreatedCallback(function(response){ - setLocation("<?php echo $block->getUrl( - 'adminhtml/order_shipment/view', - ['shipment_id' => $block->getShipment()->getId()] - ); ?>"); - }); - }, 500); + <?php echo $block->getChildHtml('shipment_packaging') ?> +<script> + require([ + 'prototype' + ], function () { -}); + setTimeout(function () { + packaging.setConfirmPackagingCallback(function () { + packaging.sendCreateLabelRequest(); + }); + packaging.setLabelCreatedCallback(function (response) { + setLocation("<?php echo $block->getUrl( +'adminhtml/order_shipment/view', +['shipment_id' => $block->getShipment()->getId()] +); ?>"); + }); + }, 500); + + }); </script> + </div> </div> </div> -</div> +</section> -<div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"> +<section class="admin__page-section"> + <div class="admin__page-section-title"> <span class="title"><?php echo __('Items Shipped') ?></span> </div> <?php echo $block->getChildHtml('shipment_items') ?> -</div> +</section> -<div class="clearfix"> - <?php echo $block->getChildHtml('shipment_packed') ?> +<section class="admin__page-section"> + <div class="admin__page-section-title"> + <span class="title"><?php echo __('Order Total') ?></span> + </div> + <div class="admin__page-section-content"> + <?php echo $block->getChildHtml('shipment_packed') ?> - <div class="order-comments-history"> - <div class="fieldset-wrapper"> - <div class="fieldset-wrapper-title"><span class="title"><?php echo __('Shipment History') ?></span></div> - <fieldset><?php echo $block->getChildHtml('order_comments') ?></fieldset> + <div class="admin__page-section-item order-comments-history"> + <div class="admin__page-section-item-title"> + <span class="title"><?php echo __('Shipment History') ?></span> + </div> + <div class="admin__page-section-item-content"><?php echo $block->getChildHtml('order_comments') ?></div> </div> </div> -</div> +</section> diff --git a/app/code/Magento/Shipping/view/adminhtml/templates/view/items.phtml b/app/code/Magento/Shipping/view/adminhtml/templates/view/items.phtml index 4b1d0f39d52bc9a77a7d69ed882368aa6fcdc7dd..1ebeae21eb75e8c9201b4a1c91df6c3d5eb09d6c 100644 --- a/app/code/Magento/Shipping/view/adminhtml/templates/view/items.phtml +++ b/app/code/Magento/Shipping/view/adminhtml/templates/view/items.phtml @@ -8,7 +8,7 @@ ?> <div class="grid"> - <table cellspacing="0" class="data"> + <table class="data-table admin__table-primary order-shipment-table"> <thead> <tr class="headings"> <th class="col-product"><span><?php echo __('Product') ?></span></th> diff --git a/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js b/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js index 566b01dc6e894f41d5521a2c958e05e4b0356c41..fca9b0553afa7a9de06030524a0259bdc4bca504 100644 --- a/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js +++ b/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js @@ -18,7 +18,7 @@ Packaging.prototype = { this.errorQtyOverLimit = params.errorQtyOverLimit; this.titleDisabledSaveBtn = params.titleDisabledSaveBtn; this.window = $('packaging_window'); - this.messages = this.window.select('.messages')[0]; + this.messages = this.window.select('.message-warning')[0]; this.packagesContent = $('packages_content'); this.template = $('package_template'); this.paramsCreateLabelRequest = {}; diff --git a/app/code/Magento/Sitemap/composer.json b/app/code/Magento/Sitemap/composer.json index 1fa5a0e4091d5cbbe06a12b2229f626960b65e15..883491985063302b2fd8b31d42895b9b2df5ccfe 100644 --- a/app/code/Magento/Sitemap/composer.json +++ b/app/code/Magento/Sitemap/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog-url-rewrite": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog-url-rewrite": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Store/App/FrontController/Plugin/RequestPreprocessor.php b/app/code/Magento/Store/App/FrontController/Plugin/RequestPreprocessor.php index 57307c083d01246894146ce4e3aa865a172bee20..4d5e21f50edd3273c794c866c5e86d6ebfc8f679 100644 --- a/app/code/Magento/Store/App/FrontController/Plugin/RequestPreprocessor.php +++ b/app/code/Magento/Store/App/FrontController/Plugin/RequestPreprocessor.php @@ -79,6 +79,7 @@ class RequestPreprocessor $response = $this->_responseFactory->create(); $response->setRedirect($redirectUrl, $redirectCode); + $response->setNoCacheHeaders(); return $response; } } diff --git a/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php b/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php index 4f03885e8cd7a910cb35abf05970bd86deb5a790..7bb9981369440c9c8062ffe6308376c8b089a05f 100644 --- a/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php +++ b/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php @@ -7,6 +7,9 @@ */ namespace Magento\Store\Model\Config\Reader; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Exception\LocalizedException; + class DefaultReader implements \Magento\Framework\App\Config\Scope\ReaderInterface { /** @@ -42,14 +45,21 @@ class DefaultReader implements \Magento\Framework\App\Config\Scope\ReaderInterfa /** * Read configuration data * + * @param null|string $scope + * @throws LocalizedException Exception is thrown when scope other than default is given * @return array */ - public function read() + public function read($scope = null) { - $config = $this->_initialConfig->getData(\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT); + $scope = $scope === null ? ScopeConfigInterface::SCOPE_TYPE_DEFAULT : $scope; + if ($scope !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + throw new \Magento\Framework\Exception\LocalizedException(__("Only default scope allowed")); + } + + $config = $this->_initialConfig->getData($scope); $collection = $this->_collectionFactory->create( - ['scope' => \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT] + ['scope' => $scope] ); $dbDefaultConfig = []; foreach ($collection as $item) { diff --git a/app/code/Magento/Store/Model/Config/Reader/Store.php b/app/code/Magento/Store/Model/Config/Reader/Store.php index c5456bcb102f9ad2952c17f33ac41f48c1ae777a..151c3625f2b1dbf596d222eaf10b3f7c9e07ce5e 100644 --- a/app/code/Magento/Store/Model/Config/Reader/Store.php +++ b/app/code/Magento/Store/Model/Config/Reader/Store.php @@ -5,6 +5,7 @@ */ namespace Magento\Store\Model\Config\Reader; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Exception\NoSuchEntityException; class Store implements \Magento\Framework\App\Config\Scope\ReaderInterface @@ -66,7 +67,7 @@ class Store implements \Magento\Framework\App\Config\Scope\ReaderInterface /** * Read configuration by code * - * @param string $code + * @param null|string $code * @return array * @throws NoSuchEntityException */ @@ -74,7 +75,7 @@ class Store implements \Magento\Framework\App\Config\Scope\ReaderInterface { if (empty($code)) { $store = $this->_storeManager->getStore(); - } elseif (($code == \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT)) { + } elseif (($code == ScopeConfigInterface::SCOPE_TYPE_DEFAULT)) { $store = $this->_storeManager->getDefaultStoreView(); } else { $store = $this->_storeFactory->create(); diff --git a/app/code/Magento/Store/Model/Config/Reader/Website.php b/app/code/Magento/Store/Model/Config/Reader/Website.php index 1448b04bf9afbf5e6b49b5e223f53b9ec2a52f69..7971deb6c9713199cfe7c85617ebe767556edb18 100644 --- a/app/code/Magento/Store/Model/Config/Reader/Website.php +++ b/app/code/Magento/Store/Model/Config/Reader/Website.php @@ -5,6 +5,8 @@ */ namespace Magento\Store\Model\Config\Reader; +use Magento\Framework\App\Config\ScopeConfigInterface; + class Website implements \Magento\Framework\App\Config\Scope\ReaderInterface { /** @@ -62,7 +64,7 @@ class Website implements \Magento\Framework\App\Config\Scope\ReaderInterface public function read($code = null) { $config = array_replace_recursive( - $this->_scopePool->getScope(\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT)->getSource(), + $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT)->getSource(), $this->_initialConfig->getData("websites|{$code}") ); diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 7dbf046110e38000509cbd55318a57efbc1b80f0..494d1c129254154208d81e6956d72027003f9dc4 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -5,6 +5,7 @@ */ namespace Magento\Store\Model; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\Http\Context; use Magento\Framework\Model\AbstractModel; @@ -55,7 +56,7 @@ class Store extends AbstractModel implements const XML_PATH_UNSECURE_BASE_URL = 'web/unsecure/base_url'; const XML_PATH_SECURE_BASE_URL = 'web/secure/base_url'; - + const XML_PATH_SECURE_IN_FRONTEND = 'web/secure/use_in_frontend'; const XML_PATH_SECURE_IN_ADMINHTML = 'web/secure/use_in_adminhtml'; @@ -479,7 +480,7 @@ class Store extends AbstractModel implements { $data = $this->_config->getValue($path, ScopeInterface::SCOPE_STORE, $this->getCode()); if (!$data) { - $data = $this->_config->getValue($path, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT); + $data = $this->_config->getValue($path, ScopeConfigInterface::SCOPE_TYPE_DEFAULT); } return $data === false ? null : $data; } @@ -755,7 +756,12 @@ class Store extends AbstractModel implements \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); - if (!$secureBaseUrl) { + if (!$secureBaseUrl || + !$this->_config->getValue( + self::XML_PATH_SECURE_IN_FRONTEND, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ) + ) { return false; } @@ -783,7 +789,7 @@ class Store extends AbstractModel implements if ($configValue == self::PRICE_SCOPE_GLOBAL) { return $this->_config->getValue( \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ); } else { return $this->_getConfig(\Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE); diff --git a/app/code/Magento/Store/Model/System/Store.php b/app/code/Magento/Store/Model/System/Store.php index 1859a2957d92f927491aaa33b541d7cab1fa068f..c3382ce1968cf415874b468b6e8126538a75ec9d 100644 --- a/app/code/Magento/Store/Model/System/Store.php +++ b/app/code/Magento/Store/Model/System/Store.php @@ -5,10 +5,12 @@ */ namespace Magento\Store\Model\System; +use Magento\Framework\Data\OptionSourceInterface; + /** * Core System Store Model */ -class Store extends \Magento\Framework\Object +class Store extends \Magento\Framework\Object implements OptionSourceInterface { /** * Website collection @@ -458,4 +460,14 @@ class Store extends \Magento\Framework\Object $this->_isAdminScopeAllowed = (bool)$value; return $this; } + + /** + * Return array of options as value-label pairs + * + * @return array Format: array(array('value' => '<value>', 'label' => '<label>'), ...) + */ + public function toOptionArray() + { + return $this->getStoreValuesForForm(); + } } diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php index 9e91f4b43281522ac0a2d3688167488893df43e3..25875ae67dd5973525a0a59cbf7e2c1635c58691 100644 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Store\Test\Unit\Model\Config\Reader; +use Magento\Framework\App\Config\ScopeConfigInterface; + class DefaultReaderTest extends \PHPUnit_Framework_TestCase { /** @@ -46,7 +48,7 @@ class DefaultReaderTest extends \PHPUnit_Framework_TestCase )->method( 'getData' )->with( - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT )->will( $this->returnValue(['config' => ['key1' => 'default_value1', 'key2' => 'default_value2']]) ); diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php index c43af1f004dfe6972d9521e3d49bd6474fb99a4b..8d305848c554f900bd521f04490c7b8f18fca6a4 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php @@ -8,6 +8,7 @@ namespace Magento\Store\Test\Unit\Model; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\ScopeInterface; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Store\Model\Store; @@ -399,7 +400,7 @@ class StoreTest extends \PHPUnit_Framework_TestCase ['catalog/price/scope', ScopeInterface::SCOPE_STORE, 'scope_code', $priceScope], [ \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null, 'USD' ], @@ -546,12 +547,15 @@ class StoreTest extends \PHPUnit_Framework_TestCase * * @param bool $expected * @param array $value + * @param bool $requestSecure + * @param bool $useSecureInFrontend * @param string|null $secureBaseUrl */ public function testIsCurrentlySecure( $expected, $value, $requestSecure = false, + $useSecureInFrontend = true, $secureBaseUrl = 'https://example.com:443' ) { /* @var ReinitableConfigInterface|PHPUnit_Framework_MockObject_MockObject $configMock */ @@ -565,6 +569,12 @@ class StoreTest extends \PHPUnit_Framework_TestCase null, $secureBaseUrl ], + [ + Store::XML_PATH_SECURE_IN_FRONTEND, + ScopeInterface::SCOPE_STORE, + null, + $useSecureInFrontend + ] ])); $this->requestMock->expects($this->any()) @@ -594,8 +604,12 @@ class StoreTest extends \PHPUnit_Framework_TestCase return [ 'secure request, no server setting' => [true, [], true], 'unsecure request, using registered port' => [true, 443], - 'unsecure request, no secure base url registered' => [false, 443, false, null], + 'unsecure request, no secure base url registered' => [false, 443, false, true, null], 'unsecure request, not using registered port' => [false, 80], + 'unsecure request, using registered port, not using secure in frontend' => [false, 443, false, false], + 'unsecure request, no secure base url registered, not using secure in frontend' => + [false, 443, false, false, null], + 'unsecure request, not using registered port, not using secure in frontend' => [false, 80, false, false], ]; } diff --git a/app/code/Magento/Store/Ui/DataProvider/Row.php b/app/code/Magento/Store/Ui/Component/Listing/Column/Store.php similarity index 59% rename from app/code/Magento/Store/Ui/DataProvider/Row.php rename to app/code/Magento/Store/Ui/Component/Listing/Column/Store.php index e48e25ca61cba0b95b52af9c35ef079e8952b0db..08b0387396799d9b63b3a2f7f1b0982605a700b8 100644 --- a/app/code/Magento/Store/Ui/DataProvider/Row.php +++ b/app/code/Magento/Store/Ui/Component/Listing/Column/Store.php @@ -3,16 +3,18 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Store\Ui\DataProvider; +namespace Magento\Store\Ui\Component\Listing\Column; use Magento\Framework\Escaper; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponentFactory; use Magento\Store\Model\System\Store as SystemStore; -use Magento\Ui\Component\Listing\RowInterface; +use Magento\Ui\Component\Listing\Columns\Column; /** * Class Store */ -class Row implements RowInterface +class Store extends Column { /** * Escaper @@ -31,26 +33,48 @@ class Row implements RowInterface /** * Constructor * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory * @param SystemStore $systemStore * @param Escaper $escaper + * @param array $components + * @param array $data */ - public function __construct(SystemStore $systemStore, Escaper $escaper) - { + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + SystemStore $systemStore, + Escaper $escaper, + array $components = [], + array $data = [] + ) { $this->systemStore = $systemStore; $this->escaper = $escaper; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + foreach ($items as & $item) { + $item[$this->getData('name')] = $this->prepareItem($item); + } + return $items; } /** * Get data * - * @param array $dataRow - * @param array $data + * @param array $item * @return mixed */ - public function getData(array $dataRow, array $data = []) + public function prepareItem(array $item) { $content = ''; - $origStores = $dataRow['store_id']; + $origStores = $item['store_id']; if (empty($origStores)) { return ''; diff --git a/app/code/Magento/Store/Ui/DataProvider/Options.php b/app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php similarity index 80% rename from app/code/Magento/Store/Ui/DataProvider/Options.php rename to app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php index 950f5bbb606932f456bbeccf859580d3af187639..308a21b9f3100446ae33487823ae10e73ffcc2e6 100644 --- a/app/code/Magento/Store/Ui/DataProvider/Options.php +++ b/app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php @@ -3,16 +3,16 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Store\Ui\DataProvider; +namespace Magento\Store\Ui\Component\Listing\Column\Store; use Magento\Framework\Escaper; +use Magento\Framework\Data\OptionSourceInterface; use Magento\Store\Model\System\Store as SystemStore; -use Magento\Ui\Component\Listing\OptionsInterface; /** - * Class Store + * Class Options */ -class Options implements OptionsInterface +class Options implements OptionSourceInterface { /** * Escaper @@ -28,6 +28,11 @@ class Options implements OptionsInterface */ protected $systemStore; + /** + * @var array + */ + protected $options; + /** * Constructor * @@ -43,11 +48,13 @@ class Options implements OptionsInterface /** * Get options * - * @param array $options * @return array */ - public function getOptions(array $options = []) + public function toOptionArray() { + if ($this->options !== null) { + return $this->options; + } $websiteCollection = $this->systemStore->getWebsiteCollection(); $groupCollection = $this->systemStore->getGroupCollection(); $storeCollection = $this->systemStore->getStoreCollection(); @@ -76,17 +83,18 @@ class Options implements OptionsInterface if (!empty($stores)) { $name = $this->escaper->escapeHtml($group->getName()); $groups[$name]['label'] = str_repeat(' ', 4) . $name; - $groups[$name]['value'] = $stores; + $groups[$name]['value'] = array_values($stores); } } } if (!empty($groups)) { $name = $this->escaper->escapeHtml($website->getName()); $currentOptions[$name]['label'] = $name; - $currentOptions[$name]['value'] = $groups; + $currentOptions[$name]['value'] = array_values($groups); } } + $this->options = array_values($currentOptions); - return array_merge_recursive($currentOptions, $options); + return $this->options; } } diff --git a/app/code/Magento/Store/Ui/DataType/Store.php b/app/code/Magento/Store/Ui/DataType/Store.php deleted file mode 100644 index 906ecaa02921f6a8e8ceef2d33074296c88bffcb..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Ui/DataType/Store.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Ui\DataType; - -use Magento\Ui\Component\Form\Element\DataType\AbstractDataType; - -/** - * Class Store - */ -class Store extends AbstractDataType -{ - // -} diff --git a/app/code/Magento/Store/composer.json b/app/code/Magento/Store/composer.json index d2c3e97181c1e980a0406709dd6c35b74a84a344..2dd66eda7c2112a897d68317d093fa5b0e9fe783 100644 --- a/app/code/Magento/Store/composer.json +++ b/app/code/Magento/Store/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-directory": "0.74.0-beta6", - "magento/module-ui": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-directory": "0.74.0-beta7", + "magento/module-ui": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Store/etc/di.xml b/app/code/Magento/Store/etc/di.xml index ebbc61f6036c8723c1fe943e07795097b63f1f6d..c1584145c2d3db3ad86924dd7ac6b0099155aa18 100644 --- a/app/code/Magento/Store/etc/di.xml +++ b/app/code/Magento/Store/etc/di.xml @@ -79,7 +79,7 @@ <arguments> <argument name="session" xsi:type="object" shared="false">Magento\Framework\Session\Generic\Proxy</argument> <argument name="isCustomEntryPoint" xsi:type="init_parameter">Magento\Store\Model\Store::CUSTOM_ENTRY_POINT_PARAM</argument> - <argument name="url" xsi:type="object" shared="false">Magento\Framework\UrlInterface</argument> + <argument name="url" xsi:type="object" shared="false">Magento\Framework\UrlInterface\Proxy</argument> </arguments> </type> <type name="Magento\Store\Model\StoreManager"> diff --git a/app/code/Magento/Store/view/base/layout/ui_components.xml b/app/code/Magento/Store/view/base/layout/ui_components.xml deleted file mode 100644 index 54811dfdf1f4035178f5a1aee01ba34923527b28..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/view/base/layout/ui_components.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/layout_generic.xsd"> - <block class="Magento\Ui\Component\Filter\Type\Select" name="filter_store"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::filter/type/select/default.phtml</argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\DataType\Text" name="store"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::data_type/text/default.phtml</argument> - </arguments> - </block> -</layout> diff --git a/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php b/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php index 356d39d0bc106519315c3fa76da8321931c116fd..a5865871a5f59f25f9d72d624d277088d5f4ae41 100644 --- a/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php +++ b/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php @@ -7,18 +7,6 @@ namespace Magento\Tax\Api\Data; interface AppliedTaxInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_TAX_RATE_KEY = 'tax_rate_key'; - - const KEY_PERCENT = 'percent'; - - const KEY_AMOUNT = 'amount'; - - const KEY_RATES = 'rates'; - /**#@-*/ - /** * Get tax rate key * diff --git a/app/code/Magento/Tax/Api/Data/AppliedTaxRateInterface.php b/app/code/Magento/Tax/Api/Data/AppliedTaxRateInterface.php index cee4ab16fd1f0acdde90bd353b3d264e4ba52b11..afd3231335ea011e6daed2e0fa5537849c376362 100644 --- a/app/code/Magento/Tax/Api/Data/AppliedTaxRateInterface.php +++ b/app/code/Magento/Tax/Api/Data/AppliedTaxRateInterface.php @@ -8,16 +8,6 @@ namespace Magento\Tax\Api\Data; interface AppliedTaxRateInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_CODE = 'code'; - - const KEY_TITLE = 'title'; - - const KEY_PERCENT = 'percent'; - /**#@-*/ - /** * Get code * diff --git a/app/code/Magento/Tax/Api/Data/OrderTaxDetailsAppliedTaxInterface.php b/app/code/Magento/Tax/Api/Data/OrderTaxDetailsAppliedTaxInterface.php index 7123087eacf565f0341178e6f9643c9a98bf7036..603d287eabff739644b9ed7ada2d397b4c59d857 100644 --- a/app/code/Magento/Tax/Api/Data/OrderTaxDetailsAppliedTaxInterface.php +++ b/app/code/Magento/Tax/Api/Data/OrderTaxDetailsAppliedTaxInterface.php @@ -9,20 +9,6 @@ namespace Magento\Tax\Api\Data; interface OrderTaxDetailsAppliedTaxInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_CODE = 'code'; - - const KEY_TITLE = 'title'; - - const KEY_PERCENT = 'percent'; - - const KEY_AMOUNT = 'amount'; - - const KEY_BASE_AMOUNT = 'base_amount'; - /**#@-*/ - /** * Get code * diff --git a/app/code/Magento/Tax/Api/Data/OrderTaxDetailsInterface.php b/app/code/Magento/Tax/Api/Data/OrderTaxDetailsInterface.php index d68de6f5858aab5c3362c60d62a1d006bc22c42d..d57fb6ba5194faac79dbcddd4e0269adb81c6dae 100644 --- a/app/code/Magento/Tax/Api/Data/OrderTaxDetailsInterface.php +++ b/app/code/Magento/Tax/Api/Data/OrderTaxDetailsInterface.php @@ -9,10 +9,6 @@ namespace Magento\Tax\Api\Data; interface OrderTaxDetailsInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - const KEY_APPLIED_TAXES = 'applied_taxes'; - - const KEY_ITEMS = 'items'; - /** * Get applied taxes at order level * diff --git a/app/code/Magento/Tax/Api/Data/OrderTaxDetailsItemInterface.php b/app/code/Magento/Tax/Api/Data/OrderTaxDetailsItemInterface.php index 905a0aa203594097e5377130679dfb4e5bb18a92..a43d4ccd7dfc4b5f1f95ed1fbf29527bdea40e89 100644 --- a/app/code/Magento/Tax/Api/Data/OrderTaxDetailsItemInterface.php +++ b/app/code/Magento/Tax/Api/Data/OrderTaxDetailsItemInterface.php @@ -9,18 +9,6 @@ namespace Magento\Tax\Api\Data; interface OrderTaxDetailsItemInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_TYPE = 'type'; - - const KEY_ITEM_ID = 'item_id'; - - const KEY_ASSOCIATED_ITEM_ID = 'associated_item_id'; - - const KEY_APPLIED_TAXES = 'applied_taxes'; - /**#@-*/ - /** * Get type (shipping, product, weee, gift wrapping, etc) * diff --git a/app/code/Magento/Tax/Api/Data/QuoteDetailsInterface.php b/app/code/Magento/Tax/Api/Data/QuoteDetailsInterface.php index f7d69e1572f86eaecfad263eeeb026ebe8f280bc..b3250a1f7caa09419ffc35169ac0362ffdc2ef2a 100644 --- a/app/code/Magento/Tax/Api/Data/QuoteDetailsInterface.php +++ b/app/code/Magento/Tax/Api/Data/QuoteDetailsInterface.php @@ -9,22 +9,6 @@ namespace Magento\Tax\Api\Data; interface QuoteDetailsInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_BILLING_ADDRESS = 'billing_address'; - - const KEY_SHIPPING_ADDRESS = 'shipping_address'; - - const KEY_CUSTOMER_TAX_CLASS_KEY = 'customer_tax_class_key'; - - const KEY_ITEMS = 'items'; - - const CUSTOMER_TAX_CLASS_ID = 'customer_tax_class_id'; - - const KEY_CUSTOMER_ID = 'customer_id'; - /**#@-*/ - /** * Get customer billing address * diff --git a/app/code/Magento/Tax/Api/Data/QuoteDetailsItemInterface.php b/app/code/Magento/Tax/Api/Data/QuoteDetailsItemInterface.php index ea3e57327f3115581853572e3159628b600c31cd..daffa01d4f87651346965eab83a723e7f806df28 100644 --- a/app/code/Magento/Tax/Api/Data/QuoteDetailsItemInterface.php +++ b/app/code/Magento/Tax/Api/Data/QuoteDetailsItemInterface.php @@ -7,32 +7,6 @@ namespace Magento\Tax\Api\Data; interface QuoteDetailsItemInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_CODE = 'code'; - - const KEY_TYPE = 'type'; - - const KEY_TAX_CLASS_KEY = 'tax_class_key'; - - const KEY_UNIT_PRICE = 'unit_price'; - - const KEY_QUANTITY = 'quantity'; - - const KEY_TAX_INCLUDED = 'tax_included'; - - const KEY_SHORT_DESCRIPTION = 'short_description'; - - const KEY_DISCOUNT_AMOUNT = 'discount_amount'; - - const KEY_PARENT_CODE = 'parent_code'; - - const KEY_ASSOCIATED_ITEM_CODE = 'associated_item_code'; - - const KEY_TAX_CLASS_ID = 'tax_class_id'; - /**#@-*/ - /** * Get code (sku or shipping code) * @@ -172,7 +146,7 @@ interface QuoteDetailsItemInterface extends \Magento\Framework\Api\ExtensibleDat /** * Get associated item code if this item is associated with another item, null otherwise * - * @return mixed|null + * @return int|null */ public function getAssociatedItemCode(); diff --git a/app/code/Magento/Tax/Api/Data/TaxClassInterface.php b/app/code/Magento/Tax/Api/Data/TaxClassInterface.php index 80774ef47c646bed3cb54e3813b7968c37536adc..632219c6ad66986690b0655198feceb4f271b0a5 100644 --- a/app/code/Magento/Tax/Api/Data/TaxClassInterface.php +++ b/app/code/Magento/Tax/Api/Data/TaxClassInterface.php @@ -9,15 +9,6 @@ namespace Magento\Tax\Api\Data; interface TaxClassInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * - * Tax class field key. - */ - const KEY_ID = 'class_id'; - const KEY_NAME = 'class_name'; - const KEY_TYPE = 'class_type'; - /**#@-*/ - /** * Get tax class ID. * diff --git a/app/code/Magento/Tax/Api/Data/TaxClassKeyInterface.php b/app/code/Magento/Tax/Api/Data/TaxClassKeyInterface.php index 9f0a25a170cbadbd71ad8e1c1e7d7cd6de7d0c27..d6f5d742ad88069a9810c5f815a3a0ac8668f18a 100644 --- a/app/code/Magento/Tax/Api/Data/TaxClassKeyInterface.php +++ b/app/code/Magento/Tax/Api/Data/TaxClassKeyInterface.php @@ -10,19 +10,10 @@ use Magento\Framework\Api\ExtensibleDataInterface; interface TaxClassKeyInterface extends ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_TYPE = 'type'; - - const KEY_VALUE = 'value'; - /**#@-*/ - /**#@+ * Constants defined for type of tax class key */ - const TYPE_ID = 'id'; - + const TYPE_ID = 'id'; const TYPE_NAME = 'name'; /**#@-*/ diff --git a/app/code/Magento/Tax/Api/Data/TaxDetailsInterface.php b/app/code/Magento/Tax/Api/Data/TaxDetailsInterface.php index f06ba96bc54ca28a6ed4e167d48bbc4e553dcd15..ce0ae30e69e15cf434a0e034be6d913afc9cc245 100644 --- a/app/code/Magento/Tax/Api/Data/TaxDetailsInterface.php +++ b/app/code/Magento/Tax/Api/Data/TaxDetailsInterface.php @@ -8,21 +8,6 @@ namespace Magento\Tax\Api\Data; interface TaxDetailsInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_SUBTOTAL = 'subtotal'; - - const KEY_TAX_AMOUNT = 'tax_amount'; - - const KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; - - const KEY_APPLIED_TAXES = 'applied_taxes'; - - const KEY_ITEMS = 'items'; - - /**#@-*/ - /** * Get subtotal * diff --git a/app/code/Magento/Tax/Api/Data/TaxDetailsItemInterface.php b/app/code/Magento/Tax/Api/Data/TaxDetailsItemInterface.php index fad3229d7076a589363cbabf9f5bcb064984e04f..0550b6614dfc76ef111e29179a96551e476a831b 100644 --- a/app/code/Magento/Tax/Api/Data/TaxDetailsItemInterface.php +++ b/app/code/Magento/Tax/Api/Data/TaxDetailsItemInterface.php @@ -8,36 +8,6 @@ namespace Magento\Tax\Api\Data; interface TaxDetailsItemInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_CODE = 'code'; - - const KEY_TYPE = 'type'; - - const KEY_TAX_PERCENT = 'tax_percent'; - - const KEY_PRICE = 'price'; - - const KEY_PRICE_INCL_TAX = 'price_incl_tax'; - - const KEY_ROW_TOTAL = 'row_total'; - - const KEY_ROW_TOTAL_INCL_TAX = 'row_total_incl_tax'; - - const KEY_ROW_TAX = 'row_tax'; - - const KEY_TAXABLE_AMOUNT = 'taxable_amount'; - - const KEY_DISCOUNT_AMOUNT = 'discount_amount'; - - const KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; - - const KEY_APPLIED_TAXES = 'applied_taxes'; - - const KEY_ASSOCIATED_ITEM_CODE = 'associated_item_code'; - /**#@-*/ - /** * Get code (sku or shipping code) * @@ -221,7 +191,7 @@ interface TaxDetailsItemInterface extends \Magento\Framework\Api\ExtensibleDataI /** * Return associated item code if this item is associated with another item, null otherwise * - * @return mixed|null + * @return int|null */ public function getAssociatedItemCode(); diff --git a/app/code/Magento/Tax/Api/Data/TaxRateInterface.php b/app/code/Magento/Tax/Api/Data/TaxRateInterface.php index 881bb7fa7e013838c558f5514af373dcbe6fceaa..34cf62414862a644f928531ce9fafe996648c32e 100644 --- a/app/code/Magento/Tax/Api/Data/TaxRateInterface.php +++ b/app/code/Magento/Tax/Api/Data/TaxRateInterface.php @@ -9,22 +9,6 @@ namespace Magento\Tax\Api\Data; interface TaxRateInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const KEY_ID = 'id'; - const KEY_COUNTRY_ID = 'tax_country_id'; - const KEY_REGION_ID = 'tax_region_id'; - const KEY_REGION_NAME = 'region_name'; - const KEY_POSTCODE = 'tax_postcode'; - const KEY_ZIP_IS_RANGE = 'zip_is_range'; - const KEY_ZIP_RANGE_FROM = 'zip_from'; - const KEY_ZIP_RANGE_TO = 'zip_to'; - const KEY_PERCENTAGE_RATE = 'rate'; - const KEY_CODE = 'code'; - const KEY_TITLES = 'titles'; - /**#@-*/ - /** * Get id * diff --git a/app/code/Magento/Tax/Api/Data/TaxRateTitleInterface.php b/app/code/Magento/Tax/Api/Data/TaxRateTitleInterface.php index 8d3991070b9565d9527c7c036aca9e45864d15f4..7dcfd2413759636b184d8e6cac0a789d6ecfacee 100644 --- a/app/code/Magento/Tax/Api/Data/TaxRateTitleInterface.php +++ b/app/code/Magento/Tax/Api/Data/TaxRateTitleInterface.php @@ -9,15 +9,6 @@ namespace Magento\Tax\Api\Data; interface TaxRateTitleInterface extends \Magento\Framework\Api\ExtensibleDataInterface { - /**#@+ - * - * Tax rate field key. - */ - const KEY_STORE_ID = 'store_id'; - - const KEY_VALUE_ID = 'value'; - /**#@-*/ - /** * Get store id * diff --git a/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php b/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php index 08a7803aa85474510a9135d22b7819dd4122c03c..84e32da4ae97439c3fbc7d8e8fccefc364b9f6cc 100644 --- a/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php +++ b/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php @@ -65,6 +65,11 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic */ protected $_taxRateCollection; + /** + * @var \Magento\Tax\Model\Calculation\Rate\Converter + */ + protected $_taxRateConverter; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Registry $registry @@ -75,6 +80,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic * @param \Magento\Tax\Helper\Data $taxData * @param \Magento\Tax\Api\TaxRateRepositoryInterface $taxRateRepository * @param \Magento\Tax\Model\TaxRateCollection $taxRateCollection + * @param \Magento\Tax\Model\Calculation\Rate\Converter $taxRateConverter * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -88,6 +94,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic \Magento\Tax\Helper\Data $taxData, \Magento\Tax\Api\TaxRateRepositoryInterface $taxRateRepository, \Magento\Tax\Model\TaxRateCollection $taxRateCollection, + \Magento\Tax\Model\Calculation\Rate\Converter $taxRateConverter, array $data = [] ) { $this->_regionFactory = $regionFactory; @@ -96,6 +103,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic $this->_taxData = $taxData; $this->_taxRateRepository = $taxRateRepository; $this->_taxRateCollection = $taxRateCollection; + $this->_taxRateConverter = $taxRateConverter; parent::__construct($context, $registry, $formFactory, $data); } @@ -127,7 +135,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic } $sessionFormValues = (array)$this->_coreRegistry->registry(RegistryConstants::CURRENT_TAX_RATE_FORM_DATA); - $formData = isset($taxRateDataObject) ? $this->extractTaxRateData($taxRateDataObject) : []; + $formData = isset($taxRateDataObject) ? $this->_taxRateConverter->createArrayFromServiceObject($taxRateDataObject) : []; $formData = array_merge($formData, $sessionFormValues); if (isset($formData['zip_is_range']) && $formData['zip_is_range'] && !isset($formData['tax_postcode'])) { @@ -286,65 +294,4 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic return parent::_prepareForm(); } - - /** - * Get Tax Rates Collection - * - * @return mixed - */ - public function getRateCollection() - { - if ($this->getData('rate_collection') == null) { - $items = $this->_taxRateCollection->getItems(); - $rates = []; - foreach ($items as $rate) { - $rateData = $rate->getData(); - if (isset($rateData['titles'])) { - foreach ($rateData['titles'] as $storeId => $value) { - $rateData['title[' . $storeId . ']'] = $value; - } - } - unset($rateData['titles']); - $rates[] = $rateData; - } - - $this->setRateCollection($rates); - } - return $this->getData('rate_collection'); - } - - /** - * Extract tax rate data in a format which is - * - * @param \Magento\Tax\Api\Data\TaxRateInterface $taxRate - * @return array - */ - protected function extractTaxRateData($taxRate) - { - $formData = [ - 'tax_calculation_rate_id' => $taxRate->getId(), - 'tax_country_id' => $taxRate->getTaxCountryId(), - 'tax_region_id' => $taxRate->getTaxRegionId(), - 'tax_postcode' => $taxRate->getTaxPostcode(), - 'code' => $taxRate->getCode(), - 'rate' => $taxRate->getRate(), - 'zip_is_range' => false, - ]; - - if ($taxRate->getZipFrom() && $taxRate->getZipTo()) { - $formData['zip_is_range'] = true; - $formData['zip_from'] = $taxRate->getZipFrom(); - $formData['zip_to'] = $taxRate->getZipTo(); - } - - if ($taxRate->getTitles()) { - $titleData = []; - foreach ($taxRate->getTitles() as $title) { - $titleData[] = [$title->getStoreId() => $title->getValue()]; - } - $formData['title'] = $titleData; - } - - return $formData; - } } diff --git a/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php b/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php index 0d2b16bee6f0dff1154bba3c025f3a0f9b0b541a..fb434ca6dd3092395c7df36a0f4cd1dfa0fdd222 100644 --- a/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php +++ b/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php @@ -297,6 +297,16 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic return $this->getUrl('tax/rate/ajaxSave/'); } + /** + * Retrieve Tax Rate load URL + * + * @return string + */ + public function getTaxRateLoadUrl() + { + return $this->getUrl('tax/rate/ajaxLoad/'); + } + /** * Extract tax rule data in a format which is * diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate.php index 7fce6e7e37d8f1d73045a7274b67efdd0e972d9a..e25e0a19a87a2752204de23adc90e6106e6c559e 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate.php @@ -6,6 +6,8 @@ namespace Magento\Tax\Controller\Adminhtml; +use Magento\Framework\Controller\ResultFactory; + /** * Adminhtml tax rate controller * @@ -19,38 +21,30 @@ class Rate extends \Magento\Backend\App\Action protected $_coreRegistry; /** - * @var \Magento\Tax\Api\TaxRateRepositoryInterface + * @var \Magento\Tax\Model\Calculation\Rate\Converter */ - protected $_taxRateRepository; + protected $_taxRateConverter; /** - * @var \Magento\Tax\Api\Data\TaxRateInterfaceFactory - */ - protected $_taxRateDataObjectFactory; - - /** - * @var \Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory + * @var \Magento\Tax\Api\TaxRateRepositoryInterface */ - protected $_taxRateTitleDataObjectFactory; + protected $_taxRateRepository; /** * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\Registry $coreRegistry + * @param \Magento\Tax\Model\Calculation\Rate\Converter $taxRateConverter * @param \Magento\Tax\Api\TaxRateRepositoryInterface $taxRateRepository - * @param \Magento\Tax\Api\Data\TaxRateInterfaceFactory $taxRateDataObjectFactory - * @param \Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory $taxRateTitleDataObjectFactory */ public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\Registry $coreRegistry, - \Magento\Tax\Api\TaxRateRepositoryInterface $taxRateRepository, - \Magento\Tax\Api\Data\TaxRateInterfaceFactory $taxRateDataObjectFactory, - \Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory $taxRateTitleDataObjectFactory + \Magento\Tax\Model\Calculation\Rate\Converter $taxRateConverter, + \Magento\Tax\Api\TaxRateRepositoryInterface $taxRateRepository ) { $this->_coreRegistry = $coreRegistry; + $this->_taxRateConverter = $taxRateConverter; $this->_taxRateRepository = $taxRateRepository; - $this->_taxRateDataObjectFactory = $taxRateDataObjectFactory; - $this->_taxRateTitleDataObjectFactory = $taxRateTitleDataObjectFactory; parent::__construct($context); } @@ -76,21 +70,15 @@ class Rate extends \Magento\Backend\App\Action /** * Initialize action * - * @return \Magento\Backend\App\Action + * @return \Magento\Backend\Model\View\Result\Page */ - protected function _initAction() + protected function initResultPage() { - $this->_view->loadLayout(); - $this->_setActiveMenu( - 'Magento_Tax::sales_tax_rates' - )->_addBreadcrumb( - __('Sales'), - __('Sales') - )->_addBreadcrumb( - __('Tax'), - __('Tax') - ); - return $this; + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Magento_Tax::sales_tax_rates') + ->addBreadcrumb(__('Sales'), __('Sales')) + ->addBreadcrumb(__('Tax'), __('Tax')); + return $resultPage; } /** @@ -100,50 +88,4 @@ class Rate extends \Magento\Backend\App\Action { return $this->_authorization->isAllowed('Magento_Tax::manage_tax'); } - - /** - * Populate a tax rate data object - * - * @param array $formData - * @return \Magento\Tax\Api\Data\TaxRateInterface - */ - protected function populateTaxRateData($formData) - { - $taxRate = $this->_taxRateDataObjectFactory->create(); - $taxRate->setId($this->extractFormData($formData, 'tax_calculation_rate_id')) - ->setTaxCountryId($this->extractFormData($formData, 'tax_country_id')) - ->setTaxRegionId($this->extractFormData($formData, 'tax_region_id')) - ->setTaxPostcode($this->extractFormData($formData, 'tax_postcode')) - ->setCode($this->extractFormData($formData, 'code')) - ->setRate($this->extractFormData($formData, 'rate')); - if (isset($formData['zip_is_range']) && $formData['zip_is_range']) { - $taxRate->setZipFrom($this->extractFormData($formData, 'zip_from')) - ->setZipTo($this->extractFormData($formData, 'zip_to'))->setZipIsRange(1); - } - - if (isset($formData['title'])) { - $titles = []; - foreach ($formData['title'] as $storeId => $value) { - $titles[] = $this->_taxRateTitleDataObjectFactory->create()->setStoreId($storeId)->setValue($value); - } - $taxRate->setTitles($titles); - } - - return $taxRate; - } - - /** - * Determines if an array value is set in the form data array and returns it. - * - * @param array $formData the form to get data from - * @param string $fieldName the key - * @return null|string - */ - protected function extractFormData($formData, $fieldName) - { - if (isset($formData[$fieldName])) { - return $formData[$fieldName]; - } - return null; - } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Add.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Add.php index 6b90cbf270fdfed7a610a436104a2ef5d1e5c8e6..2fe8a5b1572e38dcf05676653a2fd8d633ca38ed 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Add.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Add.php @@ -13,7 +13,7 @@ class Add extends \Magento\Tax\Controller\Adminhtml\Rate /** * Show Add Form * - * @return void + * @return \Magento\Backend\Model\View\Result\Page */ public function execute() { @@ -22,26 +22,18 @@ class Add extends \Magento\Tax\Controller\Adminhtml\Rate $this->_objectManager->get('Magento\Backend\Model\Session')->getFormData(true) ); - $this->_initAction()->_addBreadcrumb( - __('Manage Tax Rates'), - __('Manage Tax Rates'), - $this->getUrl('tax/rate') - )->_addBreadcrumb( - __('New Tax Rate'), - __('New Tax Rate') - )->_addContent( - $this->_view->getLayout()->createBlock( - 'Magento\Tax\Block\Adminhtml\Rate\Toolbar\Save' - )->assign( - 'header', - __('Add New Tax Rate') - )->assign( - 'form', - $this->_view->getLayout()->createBlock('Magento\Tax\Block\Adminhtml\Rate\Form', 'tax_rate_form') - ) - ); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('New Tax Rate')); - $this->_view->renderLayout(); + $resultPage = $this->initResultPage(); + $layout = $resultPage->getLayout(); + $toolbarSaveBlock = $layout->createBlock('Magento\Tax\Block\Adminhtml\Rate\Toolbar\Save') + ->assign('header', __('Add New Tax Rate')) + ->assign('form', $layout->createBlock('Magento\Tax\Block\Adminhtml\Rate\Form', 'tax_rate_form')); + + $resultPage->addBreadcrumb(__('Manage Tax Rates'), __('Manage Tax Rates'), $this->getUrl('tax/rate')) + ->addBreadcrumb(__('New Tax Rate'), __('New Tax Rate')) + ->addContent($toolbarSaveBlock); + + $resultPage->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); + $resultPage->getConfig()->getTitle()->prepend(__('New Tax Rate')); + return $resultPage; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php index fd09d178fcd755d362a1e831257dfdba6e84e182..7d5e8285ebbe6792357da00fbf158182051e69fc 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php @@ -6,36 +6,33 @@ */ namespace Magento\Tax\Controller\Adminhtml\Rate; +use Magento\Framework\Controller\ResultFactory; + class AjaxDelete extends \Magento\Tax\Controller\Adminhtml\Rate { /** * Delete Tax Rate via AJAX * - * @return void + * @return \Magento\Framework\Controller\Result\Json */ public function execute() { $rateId = (int)$this->getRequest()->getParam('tax_calculation_rate_id'); try { $this->_taxRateRepository->deleteById($rateId); - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - ['success' => true, 'error_message' => ''] - ); + $responseContent = ['success' => true, 'error_message' => '']; } catch (\Magento\Framework\Exception\LocalizedException $e) { - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - ['success' => false, 'error_message' => $e->getMessage()] - ); + $responseContent = ['success' => false, 'error_message' => $e->getMessage()]; } catch (\Exception $e) { - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - ['success' => false, 'error_message' => __('An error occurred while deleting this tax rate.')] - ); + $responseContent = [ + 'success' => false, + 'error_message' => __('An error occurred while deleting this tax rate.') + ]; } - $this->getResponse()->representJson($responseContent); + + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($responseContent); + return $resultJson; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxLoad.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxLoad.php new file mode 100755 index 0000000000000000000000000000000000000000..673ea280bab25ed504a240bfcddb25d1e2cbadfe --- /dev/null +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxLoad.php @@ -0,0 +1,50 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Tax\Controller\Adminhtml\Rate; + +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Controller\ResultFactory; + +class AjaxLoad extends \Magento\Tax\Controller\Adminhtml\Rate +{ + /** + * Json needed for the Ajax Edit Form + * + * @return void + */ + public function execute() + { + $rateId = (int)$this->getRequest()->getParam('id'); + try { + /* @var \Magento\Tax\Api\Data\TaxRateInterface */ + $taxRateDataObject = $this->_taxRateRepository->get($rateId); + /* @var array */ + $resultArray= $this->_taxRateConverter->createArrayFromServiceObject($taxRateDataObject, true); + + $responseContent = [ + 'success' => true, + 'error_message' => '', + 'result'=>$resultArray, + ]; + } catch (NoSuchEntityException $e) { + $responseContent = [ + 'success' => false, + 'error_message' => $e->getMessage(), + ]; + } catch (\Exception $e) { + $responseContent = [ + 'success' => false, + 'error_message' => __('An error occurred while loading this tax rate.'), + ]; + } + + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($responseContent); + return $resultJson; + } +} diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php index e78dc538074af4c59adb3ba4f02abe273059b2da..32ba0758fbd58b291e036ec525b06c6c3c3242c4 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php @@ -6,54 +6,47 @@ */ namespace Magento\Tax\Controller\Adminhtml\Rate; +use Magento\Framework\Controller\ResultFactory; + class AjaxSave extends \Magento\Tax\Controller\Adminhtml\Rate { /** * Save Tax Rate via AJAX * - * @return void + * @return \Magento\Framework\Controller\Result\Json */ public function execute() { - $responseContent = ''; try { $rateData = $this->_processRateData($this->getRequest()->getPostValue()); /** @var \Magento\Tax\Api\Data\TaxRateInterface $taxRate */ - $taxRate = $this->populateTaxRateData($rateData); + $taxRate = $this->_taxRateConverter->populateTaxRateData($rateData); $this->_taxRateRepository->save($taxRate); - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - [ - 'success' => true, - 'error_message' => '', - 'tax_calculation_rate_id' => $taxRate->getId(), - 'code' => $taxRate->getCode(), - ] - ); + $responseContent = [ + 'success' => true, + 'error_message' => '', + 'tax_calculation_rate_id' => $taxRate->getId(), + 'code' => $taxRate->getCode(), + ]; } catch (\Magento\Framework\Exception\LocalizedException $e) { - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - [ - 'success' => false, - 'error_message' => $e->getMessage(), - 'tax_calculation_rate_id' => '', - 'code' => '', - ] - ); + $responseContent = [ + 'success' => false, + 'error_message' => $e->getMessage(), + 'tax_calculation_rate_id' => '', + 'code' => '', + ]; } catch (\Exception $e) { - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - [ - 'success' => false, - 'error_message' => __('Something went wrong saving this rate.'), - 'tax_calculation_rate_id' => '', - 'code' => '', - ] - ); + $responseContent = [ + 'success' => false, + 'error_message' => __('Something went wrong saving this rate.'), + 'tax_calculation_rate_id' => '', + 'code' => '', + ]; } - $this->getResponse()->representJson($responseContent); + + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($responseContent); + return $resultJson; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php index bcf14907b4eff3410da0d7a637f2fb7554a00f57..9ee9be000e87c91ed034f8158df818bd74fa1897 100755 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php @@ -7,6 +7,7 @@ namespace Magento\Tax\Controller\Adminhtml\Rate; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Controller\ResultFactory; class Delete extends \Magento\Tax\Controller\Adminhtml\Rate { @@ -18,20 +19,19 @@ class Delete extends \Magento\Tax\Controller\Adminhtml\Rate public function execute() { if ($rateId = $this->getRequest()->getParam('rate')) { + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); try { $this->_taxRateRepository->deleteById($rateId); $this->messageManager->addSuccess(__('The tax rate has been deleted.')); - $this->getResponse()->setRedirect($this->getUrl("*/*/")); - return; + return $resultRedirect->setPath("*/*/"); } catch (NoSuchEntityException $e) { $this->messageManager->addError( __('Something went wrong deleting this rate because of an incorrect rate ID.') ); - $this->getResponse()->setRedirect($this->getUrl('tax/*/')); - return; + return $resultRedirect->setPath("tax/*/"); } - return $this->getDefaultResult(); } } @@ -42,11 +42,11 @@ class Delete extends \Magento\Tax\Controller\Adminhtml\Rate */ public function getDefaultResult() { - $resultRedirect = $this->resultRedirectFactory->create(); + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); if ($this->getRequest()->getServer('HTTP_REFERER')) { $resultRedirect->setRefererUrl(); } else { - $resultRedirect->setUrl($this->getUrl("*/*/")); + $resultRedirect->setPath("*/*/"); } return $resultRedirect; } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Edit.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Edit.php index 27d8003a4b22b760a015dd7aaaf1054217f3fd2c..e13ae2293e6c22bb6ec6e3493b0d6798864decd9 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Edit.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Edit.php @@ -8,13 +8,14 @@ namespace Magento\Tax\Controller\Adminhtml\Rate; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Tax\Controller\RegistryConstants; +use Magento\Framework\Controller\ResultFactory; class Edit extends \Magento\Tax\Controller\Adminhtml\Rate { /** * Show Edit Form * - * @return void + * @return \Magento\Backend\Model\View\Result\Page|\Magento\Backend\Model\View\Result\Redirect */ public function execute() { @@ -23,35 +24,27 @@ class Edit extends \Magento\Tax\Controller\Adminhtml\Rate try { $taxRateDataObject = $this->_taxRateRepository->get($rateId); } catch (NoSuchEntityException $e) { - $this->getResponse()->setRedirect($this->getUrl("*/*/")); - return; + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + return $resultRedirect->setPath("*/*/"); } - $this->_initAction()->_addBreadcrumb( - __('Manage Tax Rates'), - __('Manage Tax Rates'), - $this->getUrl('tax/rate') - )->_addBreadcrumb( - __('Edit Tax Rate'), - __('Edit Tax Rate') - )->_addContent( - $this->_view->getLayout()->createBlock( - 'Magento\Tax\Block\Adminhtml\Rate\Toolbar\Save' - )->assign( - 'header', - __('Edit Tax Rate') - )->assign( + $resultPage = $this->initResultPage(); + $layout = $resultPage->getLayout(); + + $toolbarSaveBlock = $layout->createBlock('Magento\Tax\Block\Adminhtml\Rate\Toolbar\Save') + ->assign('header', __('Edit Tax Rate')) + ->assign( 'form', - $this->_view->getLayout()->createBlock( - 'Magento\Tax\Block\Adminhtml\Rate\Form', - 'tax_rate_form' - )->setShowLegend( - true - ) - ) - ); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); - $this->_view->getPage()->getConfig()->getTitle()->prepend(sprintf("%s", $taxRateDataObject->getCode())); - $this->_view->renderLayout(); + $layout->createBlock('Magento\Tax\Block\Adminhtml\Rate\Form', 'tax_rate_form')->setShowLegend(true) + ); + + $resultPage->addBreadcrumb(__('Manage Tax Rates'), __('Manage Tax Rates'), $this->getUrl('tax/rate')) + ->addBreadcrumb(__('Edit Tax Rate'), __('Edit Tax Rate')) + ->addContent($toolbarSaveBlock); + + $resultPage->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); + $resultPage->getConfig()->getTitle()->prepend(sprintf("%s", $taxRateDataObject->getCode())); + return $resultPage; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Index.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Index.php index 17e1349e4f05aa59274a4c841e3c504c79d5dcd0..d38d6ddd9af1407a69f268cb085eafcf9d84ad77 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Index.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Index.php @@ -11,12 +11,13 @@ class Index extends \Magento\Tax\Controller\Adminhtml\Rate /** * Show Main Grid * - * @return void + * @return \Magento\Backend\Model\View\Result\Page */ public function execute() { - $this->_initAction()->_addBreadcrumb(__('Manage Tax Rates'), __('Manage Tax Rates')); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); - $this->_view->renderLayout(); + $resultPage = $this->initResultPage(); + $resultPage->addBreadcrumb(__('Manage Tax Rates'), __('Manage Tax Rates')); + $resultPage->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); + return $resultPage; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php index 8a7e1cba1c0c49b6c3c86117e2101c217b023258..36dbcc284eabb831c206477b1da004c886686429 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php @@ -7,16 +7,19 @@ namespace Magento\Tax\Controller\Adminhtml\Rate; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Controller\ResultFactory; class Save extends \Magento\Tax\Controller\Adminhtml\Rate { /** * Save Rate and Data * - * @return void + * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() { + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $ratePost = $this->getRequest()->getPostValue(); if ($ratePost) { $rateId = $this->getRequest()->getParam('tax_calculation_rate_id'); @@ -29,22 +32,19 @@ class Save extends \Magento\Tax\Controller\Adminhtml\Rate } try { - $taxData = $this->populateTaxRateData($ratePost); + $taxData = $this->_taxRateConverter->populateTaxRateData($ratePost); $this->_taxRateRepository->save($taxData); $this->messageManager->addSuccess(__('The tax rate has been saved.')); - $this->getResponse()->setRedirect($this->getUrl("*/*/")); - return; + return $resultRedirect->setPath('*/*/'); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData($ratePost); $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addError($e->getMessage()); } - - $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl($this->getUrl('*'))); - return; + return $resultRedirect->setUrl($this->_redirect->getRedirectUrl($this->getUrl('*'))); } - $this->getResponse()->setRedirect($this->getUrl('tax/rate')); + return $resultRedirect->setPath('tax/rate'); } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule.php index 577babe2ae7a01a64ba730f0d44e344e48a02555..f4a88b5f036653086711718297624377d27bfd53 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule.php @@ -12,6 +12,7 @@ namespace Magento\Tax\Controller\Adminhtml; use Magento\Backend\App\Action; +use Magento\Framework\Controller\ResultFactory; class Rule extends \Magento\Backend\App\Action { @@ -49,21 +50,15 @@ class Rule extends \Magento\Backend\App\Action /** * Initialize action * - * @return $this + * @return \Magento\Backend\Model\View\Result\Page */ - protected function _initAction() + protected function initResultPage() { - $this->_view->loadLayout(); - $this->_setActiveMenu( - 'Magento_Tax::sales_tax_rules' - )->_addBreadcrumb( - __('Tax'), - __('Tax') - )->_addBreadcrumb( - __('Tax Rules'), - __('Tax Rules') - ); - return $this; + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Magento_Tax::sales_tax_rules') + ->addBreadcrumb(__('Tax'), __('Tax')) + ->addBreadcrumb(__('Tax Rules'), __('Tax Rules')); + return $resultPage; } /** diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Delete.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Delete.php index 4fff21c62f6352e4c1c4ac14b9504864755317bf..c0a26cbcecf15cefa89d893a60744dc653cc6c05 100755 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Delete.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Delete.php @@ -6,25 +6,28 @@ */ namespace Magento\Tax\Controller\Adminhtml\Rule; +use Magento\Framework\Controller\ResultFactory; + class Delete extends \Magento\Tax\Controller\Adminhtml\Rule { /** - * @return \Magento\Backend\Model\View\Result\Redirect|void + * + * @throws \Exception + * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() { + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $ruleId = (int)$this->getRequest()->getParam('rule'); try { $this->ruleService->deleteById($ruleId); $this->messageManager->addSuccess(__('The tax rule has been deleted.')); - $this->_redirect('tax/*/'); - return; + return $resultRedirect->setPath('tax/*/'); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { $this->messageManager->addError(__('This rule no longer exists.')); - $this->_redirect('tax/*/'); - return; + return $resultRedirect->setPath('tax/*/'); } - return $this->getDefaultResult(); } /** @@ -34,7 +37,8 @@ class Delete extends \Magento\Tax\Controller\Adminhtml\Rule */ public function getDefaultResult() { - $resultRedirect = $this->resultRedirectFactory->create(); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setUrl($this->_redirect->getRedirectUrl($this->getUrl('*'))); } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Edit.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Edit.php index 86663f854fd90536784575fc2dff3b1fd501de68..ebbabcf833aed5f6eea84d58dfd91ffa35514a08 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Edit.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Edit.php @@ -6,11 +6,12 @@ */ namespace Magento\Tax\Controller\Adminhtml\Rule; +use Magento\Framework\Controller\ResultFactory; class Edit extends \Magento\Tax\Controller\Adminhtml\Rule { /** - * @return void + * @return \Magento\Backend\Model\View\Result\Page|\Magento\Backend\Model\View\Result\Redirect */ public function execute() { @@ -25,8 +26,9 @@ class Edit extends \Magento\Tax\Controller\Adminhtml\Rule } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { $backendSession->unsRuleData(); $this->messageManager->addError(__('This rule no longer exists.')); - $this->_redirect('tax/*/'); - return; + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + return $resultRedirect->setPath('tax/*/'); } } else { $pageTitle = __('New Tax Rule'); @@ -36,9 +38,10 @@ class Edit extends \Magento\Tax\Controller\Adminhtml\Rule $this->_coreRegistry->register('tax_rule_form_data', $data); } $breadcrumb = $taxRuleId ? __('Edit Rule') : __('New Rule'); - $this->_initAction()->_addBreadcrumb($breadcrumb, $breadcrumb); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Tax Rules')); - $this->_view->getPage()->getConfig()->getTitle()->prepend($pageTitle); - $this->_view->renderLayout(); + $resultPage = $this->initResultPage(); + $resultPage->addBreadcrumb($breadcrumb, $breadcrumb); + $resultPage->getConfig()->getTitle()->prepend(__('Tax Rules')); + $resultPage->getConfig()->getTitle()->prepend($pageTitle); + return $resultPage; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Index.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Index.php index f64f5a2db19b11335a0f514c2c083a39367ac9a2..b3ea7586cf90bd507139b000ea52e8f3ac414735 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Index.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Index.php @@ -10,12 +10,12 @@ namespace Magento\Tax\Controller\Adminhtml\Rule; class Index extends \Magento\Tax\Controller\Adminhtml\Rule { /** - * @return $this + * @return \Magento\Backend\Model\View\Result\Page */ public function execute() { - $this->_initAction(); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Tax Rules')); - $this->_view->renderLayout(); + $resultPage = $this->initResultPage(); + $resultPage->getConfig()->getTitle()->prepend(__('Tax Rules')); + return $resultPage; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule/NewAction.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule/NewAction.php index 94b15bc53b7eed8d741b5b202efd0e8167ad463f..79f4fa7d752e72dafcb21e342d5aa95dd3af57fd 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule/NewAction.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule/NewAction.php @@ -6,14 +6,17 @@ */ namespace Magento\Tax\Controller\Adminhtml\Rule; +use Magento\Framework\Controller\ResultFactory; class NewAction extends \Magento\Tax\Controller\Adminhtml\Rule { /** - * @return void + * @return \Magento\Backend\Model\View\Result\Forward */ public function execute() { - $this->_forward('edit'); + /** @var \Magento\Backend\Model\View\Result\Forward $resultForward */ + $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD); + return $resultForward->forward('edit'); } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php index 155c2bb0b76e3cad9efc59090547a3098cba684e..fdcaa2f15c127540fc9f07713b2ec3dc17da8a1d 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php @@ -6,14 +6,17 @@ */ namespace Magento\Tax\Controller\Adminhtml\Rule; +use Magento\Framework\Controller\ResultFactory; class Save extends \Magento\Tax\Controller\Adminhtml\Rule { /** - * @return void + * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() { + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $postData = $this->getRequest()->getPostValue(); if ($postData) { $postData['calculate_subtotal'] = $this->getRequest()->getParam('calculate_subtotal', 0); @@ -24,12 +27,9 @@ class Save extends \Magento\Tax\Controller\Adminhtml\Rule $this->messageManager->addSuccess(__('The tax rule has been saved.')); if ($this->getRequest()->getParam('back')) { - $this->_redirect('tax/*/edit', ['rule' => $taxRule->getId()]); - return; + return $resultRedirect->setPath('tax/*/edit', ['rule' => $taxRule->getId()]); } - - $this->_redirect('tax/*/'); - return; + return $resultRedirect->setPath('tax/*/'); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { @@ -37,9 +37,8 @@ class Save extends \Magento\Tax\Controller\Adminhtml\Rule } $this->_objectManager->get('Magento\Backend\Model\Session')->setRuleData($postData); - $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl($this->getUrl('*'))); - return; + return $resultRedirect->setUrl($this->_redirect->getRedirectUrl($this->getUrl('*'))); } - $this->getResponse()->setRedirect($this->getUrl('tax/rule')); + return $resultRedirect->setPath('tax/rule'); } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php index d817e1134442fe0602b5eb583fa7f6293f4407a7..20e413ed5e78f886d9fbb4be3b8562c1249bc022 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php @@ -6,36 +6,32 @@ */ namespace Magento\Tax\Controller\Adminhtml\Tax; +use Magento\Framework\Controller\ResultFactory; + class AjaxDelete extends \Magento\Tax\Controller\Adminhtml\Tax { /** * Delete Tax Class via AJAX * - * @return void + * @return \Magento\Framework\Controller\Result\Json */ public function execute() { $classId = (int)$this->getRequest()->getParam('class_id'); try { $this->taxClassRepository->deleteById($classId); - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - ['success' => true, 'error_message' => ''] - ); + $responseContent = ['success' => true, 'error_message' => '']; } catch (\Magento\Framework\Exception\LocalizedException $e) { - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - ['success' => false, 'error_message' => $e->getMessage()] - ); + $responseContent = ['success' => false, 'error_message' => $e->getMessage()]; } catch (\Exception $e) { - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - ['success' => false, 'error_message' => __('Something went wrong deleting this tax class.')] - ); + $responseContent = [ + 'success' => false, + 'error_message' => __('Something went wrong deleting this tax class.') + ]; } - $this->getResponse()->representJson($responseContent); + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($responseContent); + return $resultJson; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php index f338428b3ddb8dcfd77a1ffdf93f6de637b4cfa8..b8f72a7fa6d439e9849df9c4c81c57c2e8655931 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php @@ -6,12 +6,14 @@ */ namespace Magento\Tax\Controller\Adminhtml\Tax; +use Magento\Framework\Controller\ResultFactory; + class AjaxSave extends \Magento\Tax\Controller\Adminhtml\Tax { /** * Save Tax Class via AJAX * - * @return void + * @return \Magento\Framework\Controller\Result\Json */ public function execute() { @@ -24,30 +26,30 @@ class AjaxSave extends \Magento\Tax\Controller\Adminhtml\Tax ->setClassName($this->_processClassName((string)$this->getRequest()->getPost('class_name'))); $taxClassId = $this->taxClassRepository->save($taxClass); - $responseContent = $this->_objectManager->get( - 'Magento\Framework\Json\Helper\Data' - )->jsonEncode( - [ - 'success' => true, - 'error_message' => '', - 'class_id' => $taxClassId, - 'class_name' => $taxClass->getClassName(), - ] - ); + $responseContent = [ + 'success' => true, + 'error_message' => '', + 'class_id' => $taxClassId, + 'class_name' => $taxClass->getClassName(), + ]; } catch (\Magento\Framework\Exception\LocalizedException $e) { - $responseContent = $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode( - ['success' => false, 'error_message' => $e->getMessage(), 'class_id' => '', 'class_name' => ''] - ); + $responseContent = [ + 'success' => false, + 'error_message' => $e->getMessage(), + 'class_id' => '', + 'class_name' => '' + ]; } catch (\Exception $e) { - $responseContent = $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode( - [ - 'success' => false, - 'error_message' => __('Something went wrong saving this tax class.'), - 'class_id' => '', - 'class_name' => '', - ] - ); + $responseContent = [ + 'success' => false, + 'error_message' => __('Something went wrong saving this tax class.'), + 'class_id' => '', + 'class_name' => '', + ]; } - $this->getResponse()->representJson($responseContent); + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($responseContent); + return $resultJson; } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php index 71db454cc337847c5f47dbef985ebf9e06360a82..9fede0b0238787abcc72a691b7473f588a90434b 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php @@ -6,6 +6,9 @@ */ namespace Magento\Tax\Controller\Adminhtml\Tax; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Controller\ResultFactory; + class IgnoreTaxNotification extends \Magento\Tax\Controller\Adminhtml\Tax { /** @@ -32,7 +35,7 @@ class IgnoreTaxNotification extends \Magento\Tax\Controller\Adminhtml\Tax /** * Set tax ignore notification flag and redirect back * - * @return \Magento\Framework\App\ResponseInterface + * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() { @@ -41,7 +44,7 @@ class IgnoreTaxNotification extends \Magento\Tax\Controller\Adminhtml\Tax try { $path = 'tax/notification/ignore_' . $section; $this->_objectManager->get('Magento\Config\Model\Resource\Config') - ->saveConfig($path, 1, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, 0); + ->saveConfig($path, 1, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0); } catch (\Exception $e) { $this->messageManager->addError($e->getMessage()); } @@ -51,6 +54,8 @@ class IgnoreTaxNotification extends \Magento\Tax\Controller\Adminhtml\Tax $this->_cacheTypeList->cleanType('block_html'); $this->_eventManager->dispatch('adminhtml_cache_refresh_type', ['type' => 'block_html']); - $this->getResponse()->setRedirect($this->_redirect->getRefererUrl()); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + return $resultRedirect->setRefererUrl(); } } diff --git a/app/code/Magento/Tax/Model/Calculation/Rate.php b/app/code/Magento/Tax/Model/Calculation/Rate.php index 18dde7c54f14d54945d1625e034e07ce7833f502..fae528a7d943f8b48b5023d3aaf2ad468a62bb98 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rate.php +++ b/app/code/Magento/Tax/Model/Calculation/Rate.php @@ -20,8 +20,24 @@ use Magento\Tax\Api\Data\TaxRateInterface; * @method \Magento\Tax\Model\Resource\Calculation\Rate getResource() * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Rate extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Tax\Api\Data\TaxRateInterface +class Rate extends \Magento\Framework\Model\AbstractExtensibleModel implements TaxRateInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_ID = 'id'; + const KEY_COUNTRY_ID = 'tax_country_id'; + const KEY_REGION_ID = 'tax_region_id'; + const KEY_REGION_NAME = 'region_name'; + const KEY_POSTCODE = 'tax_postcode'; + const KEY_ZIP_IS_RANGE = 'zip_is_range'; + const KEY_ZIP_RANGE_FROM = 'zip_from'; + const KEY_ZIP_RANGE_TO = 'zip_to'; + const KEY_PERCENTAGE_RATE = 'rate'; + const KEY_CODE = 'code'; + const KEY_TITLES = 'titles'; + /**#@-*/ + /** * List of tax titles * diff --git a/app/code/Magento/Tax/Model/Calculation/Rate/Converter.php b/app/code/Magento/Tax/Model/Calculation/Rate/Converter.php index 7a407da4de340f4d8a8c82bc2df877786ecdcc3a..5fd8da907a5d8b81a297511758895d0dfa2156bd 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rate/Converter.php +++ b/app/code/Magento/Tax/Model/Calculation/Rate/Converter.php @@ -12,6 +12,27 @@ namespace Magento\Tax\Model\Calculation\Rate; */ class Converter { + /** + * @var \Magento\Tax\Api\Data\TaxRateInterfaceFactory + */ + protected $taxRateDataObjectFactory; + + /** + * @var \Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory + */ + protected $taxRateTitleDataObjectFactory; + + /** + * @param \Magento\Tax\Api\Data\TaxRateInterfaceFactory $taxRateDataObjectFactory + * @param \Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory $taxRateTitleDataObjectFactory, + */ + public function __construct( + \Magento\Tax\Api\Data\TaxRateInterfaceFactory $taxRateDataObjectFactory, + \Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory $taxRateTitleDataObjectFactory + ) { + $this->taxRateDataObjectFactory = $taxRateDataObjectFactory; + $this->taxRateTitleDataObjectFactory = $taxRateTitleDataObjectFactory; + } /** * Convert a tax rate data object to an array of associated titles * @@ -29,4 +50,105 @@ class Converter } return $titleData; } + + /** + * Extract tax rate data in a format which is + * + * @param \Magento\Tax\Api\Data\TaxRateInterface $taxRate + * @param Boolean $returnNumericLogic + * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function createArrayFromServiceObject( + \Magento\Tax\Api\Data\TaxRateInterface $taxRate, + $returnNumericLogic = false + ) { + $taxRateFormData = [ + 'tax_calculation_rate_id' => $taxRate->getId(), + 'tax_country_id' => $taxRate->getTaxCountryId(), + 'tax_region_id' => $taxRate->getTaxRegionId(), + 'tax_postcode' => $taxRate->getTaxPostcode(), + 'code' => $taxRate->getCode(), + 'rate' => $taxRate->getRate(), + 'zip_is_range' => $returnNumericLogic?0:false, + ]; + + if ($taxRate->getZipFrom() && $taxRate->getZipTo()) { + $taxRateFormData['zip_is_range'] = $returnNumericLogic?1:true; + $taxRateFormData['zip_from'] = $taxRate->getZipFrom(); + $taxRateFormData['zip_to'] = $taxRate->getZipTo(); + } + + if ($returnNumericLogic) { + //format for the ajax on multiple sites titles + $titleArray=($this->createTitleArrayFromServiceObject($taxRate)); + if (is_array($titleArray)) { + foreach ($titleArray as $storeId => $title) { + $taxRateFormData['title[' . $storeId . ']']=$title; + } + } + } else { + //format for the form array on multiple sites titles + $titleArray=($this->createTitleArrayFromServiceObject($taxRate)); + if (is_array($titleArray)) { + $titleData = []; + foreach ($titleArray as $storeId => $title) { + $titleData[] = [$storeId => $title]; + } + if (count($titleArray)>0) { + $taxRateFormData['title'] = $titleData; + } + } + } + + return $taxRateFormData; + } + + + /** + * Convert an array to a tax rate data object + * + * @param array $formData + * @return \Magento\Tax\Api\Data\TaxRateInterface + */ + public function populateTaxRateData($formData) + { + $taxRate = $this->taxRateDataObjectFactory->create(); + $taxRate->setId($this->extractFormData($formData, 'tax_calculation_rate_id')) + ->setTaxCountryId($this->extractFormData($formData, 'tax_country_id')) + ->setTaxRegionId($this->extractFormData($formData, 'tax_region_id')) + ->setTaxPostcode($this->extractFormData($formData, 'tax_postcode')) + ->setCode($this->extractFormData($formData, 'code')) + ->setRate($this->extractFormData($formData, 'rate')); + if (isset($formData['zip_is_range']) && $formData['zip_is_range']) { + $taxRate->setZipFrom($this->extractFormData($formData, 'zip_from')) + ->setZipTo($this->extractFormData($formData, 'zip_to'))->setZipIsRange(1); + } + + if (isset($formData['title'])) { + $titles = []; + foreach ($formData['title'] as $storeId => $value) { + $titles[] = $this->taxRateTitleDataObjectFactory->create()->setStoreId($storeId)->setValue($value); + } + $taxRate->setTitles($titles); + } + + return $taxRate; + } + + /** + * Determines if an array value is set in the form data array and returns it. + * + * @param array $formData the form to get data from + * @param string $fieldName the key + * @return null|string + */ + protected function extractFormData($formData, $fieldName) + { + if (isset($formData[$fieldName])) { + return $formData[$fieldName]; + } + return null; + } } diff --git a/app/code/Magento/Tax/Model/Calculation/Rate/Title.php b/app/code/Magento/Tax/Model/Calculation/Rate/Title.php index a98b220548940e240774250f868c8b1abb8c4f1d..141e62435538b94a97d91671966161b6bf174b7c 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rate/Title.php +++ b/app/code/Magento/Tax/Model/Calculation/Rate/Title.php @@ -17,9 +17,16 @@ namespace Magento\Tax\Model\Calculation\Rate; use Magento\Tax\Api\Data\TaxRateTitleInterface; -class Title extends \Magento\Framework\Model\AbstractExtensibleModel implements - \Magento\Tax\Api\Data\TaxRateTitleInterface +class Title extends \Magento\Framework\Model\AbstractExtensibleModel implements TaxRateTitleInterface { + /**#@+ + * + * Tax rate field key. + */ + const KEY_STORE_ID = 'store_id'; + const KEY_VALUE_ID = 'value'; + /**#@-*/ + /** * @return void */ diff --git a/app/code/Magento/Tax/Model/Calculation/RateRepository.php b/app/code/Magento/Tax/Model/Calculation/RateRepository.php index a185acd15844412198f779b0efd4dc58e224a7fa..6f099ea27ae35038fac754ea19d97066355c7b47 100644 --- a/app/code/Magento/Tax/Model/Calculation/RateRepository.php +++ b/app/code/Magento/Tax/Model/Calculation/RateRepository.php @@ -15,7 +15,7 @@ use Magento\Framework\Api\SortOrder; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\AlreadyExistsException; -use Magento\Tax\Api\Data\TaxRateInterface as TaxRateDataObject; +use Magento\Tax\Model\Calculation\Rate; use Magento\Tax\Model\Calculation\Rate\Converter; use Magento\Tax\Model\Resource\Calculation\Rate\Collection; @@ -210,7 +210,7 @@ class RateRepository implements \Magento\Tax\Api\TaxRateRepositoryInterface protected function translateField($field) { switch ($field) { - case TaxRateDataObject::KEY_REGION_NAME: + case Rate::KEY_REGION_NAME: return 'region_table.code'; default: return "main_table." . $field; diff --git a/app/code/Magento/Tax/Model/Calculation/Rule.php b/app/code/Magento/Tax/Model/Calculation/Rule.php index 13d287ce5da36b67ece5d16a634a1ba3a743ca44..dc7e0cfac6f2c4932e6c1515b277483e78e88a7c 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rule.php +++ b/app/code/Magento/Tax/Model/Calculation/Rule.php @@ -21,21 +21,14 @@ class Rule extends \Magento\Framework\Model\AbstractExtensibleModel implements T * * Tax rule field key. */ - const KEY_ID = 'id'; - - const KEY_CODE = 'code'; - + const KEY_ID = 'id'; + const KEY_CODE = 'code'; const KEY_PRIORITY = 'priority'; - const KEY_POSITION = 'position'; - const KEY_CUSTOMER_TAX_CLASS_IDS = 'customer_tax_class_ids'; - - const KEY_PRODUCT_TAX_CLASS_IDS = 'product_tax_class_ids'; - - const KEY_TAX_RATE_IDS = 'tax_rate_ids'; - - const KEY_CALCULATE_SUBTOTAL = 'calculate_subtotal'; + const KEY_PRODUCT_TAX_CLASS_IDS = 'product_tax_class_ids'; + const KEY_TAX_RATE_IDS = 'tax_rate_ids'; + const KEY_CALCULATE_SUBTOTAL = 'calculate_subtotal'; /**#@-*/ /** diff --git a/app/code/Magento/Tax/Model/ClassModel.php b/app/code/Magento/Tax/Model/ClassModel.php index 603fc708d47286e0dffdd25f8724756445f6cac1..610527d58eb625ed32510e99dabbb11d58af3bc8 100644 --- a/app/code/Magento/Tax/Model/ClassModel.php +++ b/app/code/Magento/Tax/Model/ClassModel.php @@ -19,6 +19,14 @@ use Magento\Tax\Api\Data\TaxClassInterface; class ClassModel extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Tax\Api\Data\TaxClassInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_ID = 'class_id'; + const KEY_NAME = 'class_name'; + const KEY_TYPE = 'class_type'; + /**#@-*/ + /** * Defines Customer Tax Class string */ diff --git a/app/code/Magento/Tax/Model/ClassModelRegistry.php b/app/code/Magento/Tax/Model/ClassModelRegistry.php index e4667c061776813e7fa833bae372904527505eb5..da438fcbdf3d55ddb4d5127a36b89d402ec2e4cc 100644 --- a/app/code/Magento/Tax/Model/ClassModelRegistry.php +++ b/app/code/Magento/Tax/Model/ClassModelRegistry.php @@ -7,7 +7,6 @@ namespace Magento\Tax\Model; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Tax\Api\Data\TaxClassInterface; use Magento\Tax\Model\ClassModel as TaxClassModel; use Magento\Tax\Model\ClassModelFactory as TaxClassModelFactory; @@ -67,7 +66,7 @@ class ClassModelRegistry $taxClassModel = $this->taxClassModelFactory->create()->load($taxClassId); if (!$taxClassModel->getId()) { // tax class does not exist - throw NoSuchEntityException::singleField(TaxClassInterface::KEY_ID, $taxClassId); + throw NoSuchEntityException::singleField(TaxClassModel::KEY_ID, $taxClassId); } $this->taxClassRegistryById[$taxClassModel->getId()] = $taxClassModel; return $taxClassModel; diff --git a/app/code/Magento/Tax/Model/Config/Notification.php b/app/code/Magento/Tax/Model/Config/Notification.php index c886452442406056cb369dd15210a1c32b0c9829..f4b395a290856cf26c36fae743ac7a3ce9797c9b 100644 --- a/app/code/Magento/Tax/Model/Config/Notification.php +++ b/app/code/Magento/Tax/Model/Config/Notification.php @@ -5,6 +5,8 @@ */ namespace Magento\Tax\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; + /** * Tax Config Notification */ @@ -59,7 +61,7 @@ class Notification extends \Magento\Framework\App\Config\Value */ protected function _resetNotificationFlag($path) { - $this->resourceConfig->saveConfig($path, 0, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, 0); + $this->resourceConfig->saveConfig($path, 0, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0); return $this; } } diff --git a/app/code/Magento/Tax/Model/Rate/Source.php b/app/code/Magento/Tax/Model/Rate/Source.php index 8e4342ca28f161887bfc6aecf3e1d1f6ccb41b44..0d999d6698b6ba76630b3d81a815c8649e466cb5 100644 --- a/app/code/Magento/Tax/Model/Rate/Source.php +++ b/app/code/Magento/Tax/Model/Rate/Source.php @@ -8,8 +8,8 @@ namespace Magento\Tax\Model\Rate; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Convert\Object as Converter; -use Magento\Tax\Api\Data\TaxRateInterface as TaxRate; use Magento\Tax\Api\TaxRateRepositoryInterface; +use Magento\Tax\Model\Calculation\Rate; /** * Tax rate source model. @@ -57,8 +57,8 @@ class Source implements \Magento\Framework\Data\OptionSourceInterface $searchResults = $this->taxRateRepository->getList($searchCriteria); $this->options = $this->converter->toOptionArray( $searchResults->getItems(), - TaxRate::KEY_ID, - TaxRate::KEY_CODE + Rate::KEY_ID, + Rate::KEY_CODE ); } return $this->options; diff --git a/app/code/Magento/Tax/Model/Sales/Order/Details.php b/app/code/Magento/Tax/Model/Sales/Order/Details.php index 5161ab9fe6f7397f08cb88972033a8a6be6f6ef4..0294aff0f68eeef1f3e903a3ecbc85246d4fd3c9 100644 --- a/app/code/Magento/Tax/Model/Sales/Order/Details.php +++ b/app/code/Magento/Tax/Model/Sales/Order/Details.php @@ -13,6 +13,13 @@ namespace Magento\Tax\Model\Sales\Order; class Details extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Tax\Api\Data\OrderTaxDetailsInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_APPLIED_TAXES = 'applied_taxes'; + const KEY_ITEMS = 'items'; + /**#@-*/ + /** * {@inheritdoc} */ diff --git a/app/code/Magento/Tax/Model/Sales/Order/Tax.php b/app/code/Magento/Tax/Model/Sales/Order/Tax.php index 29ce7e404f5696bcff549d3b276f6b14f6aea1d2..3b67f9222800f2f55585bff22409966003799d2e 100644 --- a/app/code/Magento/Tax/Model/Sales/Order/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Order/Tax.php @@ -25,6 +25,16 @@ namespace Magento\Tax\Model\Sales\Order; class Tax extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_CODE = 'code'; + const KEY_TITLE = 'title'; + const KEY_PERCENT = 'percent'; + const KEY_AMOUNT = 'amount'; + const KEY_BASE_AMOUNT = 'base_amount'; + /**#@-*/ + /** * @return void */ diff --git a/app/code/Magento/Tax/Model/Sales/Order/Tax/Item.php b/app/code/Magento/Tax/Model/Sales/Order/Tax/Item.php index a6b6148ed0c9eaca83d07b74c4d32f53ce3a1e74..8ecadf3eec08696f763a1f72ea1bbfa256dcd575 100644 --- a/app/code/Magento/Tax/Model/Sales/Order/Tax/Item.php +++ b/app/code/Magento/Tax/Model/Sales/Order/Tax/Item.php @@ -11,6 +11,15 @@ namespace Magento\Tax\Model\Sales\Order\Tax; class Item extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Tax\Api\Data\OrderTaxDetailsItemInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_TYPE = 'type'; + const KEY_ITEM_ID = 'item_id'; + const KEY_ASSOCIATED_ITEM_ID = 'associated_item_id'; + const KEY_APPLIED_TAXES = 'applied_taxes'; + /**#@-*/ + /** * {@inheritdoc} */ diff --git a/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php b/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php index c665dfd00e8f8a65f487faacb618c1475991b10b..fed06b4dd1983da04c39ff4625bf22c0626a4707 100644 --- a/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php +++ b/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php @@ -10,7 +10,8 @@ namespace Magento\Tax\Model\Sales\Order; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterfaceFactory as TaxDetailsDataObjectFactory; use Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface as AppliedTax; -use Magento\Tax\Api\Data\OrderTaxDetailsItemInterface as Item; +use Magento\Tax\Model\Sales\Order\Tax; +use Magento\Tax\Model\Sales\Order\Tax\Item; class TaxManagement implements \Magento\Tax\Api\OrderTaxManagementInterface { @@ -83,7 +84,7 @@ class TaxManagement implements \Magento\Tax\Api\OrderTaxManagementInterface * Aggregate item applied taxes to get order applied taxes * * @param TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory - * @param Item[] $items + * @param \Magento\Tax\Api\Data\OrderTaxDetailsItemInterface[] $items * @return AppliedTax[] */ protected function aggregateAppliedTaxes(TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory, $items) @@ -96,25 +97,25 @@ class TaxManagement implements \Magento\Tax\Api\OrderTaxManagementInterface $code = $itemAppliedTax->getCode(); if (!isset($orderAppliedTaxesData[$code])) { $orderAppliedTaxesData[$code] = [ - AppliedTax::KEY_CODE => $code, - AppliedTax::KEY_TITLE => $itemAppliedTax->getTitle(), - AppliedTax::KEY_PERCENT => $itemAppliedTax->getPercent(), - AppliedTax::KEY_AMOUNT => $itemAppliedTax->getAmount(), - AppliedTax::KEY_BASE_AMOUNT => $itemAppliedTax->getBaseAmount(), + Tax::KEY_CODE => $code, + Tax::KEY_TITLE => $itemAppliedTax->getTitle(), + Tax::KEY_PERCENT => $itemAppliedTax->getPercent(), + Tax::KEY_AMOUNT => $itemAppliedTax->getAmount(), + Tax::KEY_BASE_AMOUNT => $itemAppliedTax->getBaseAmount(), ]; } else { - $orderAppliedTaxesData[$code][AppliedTax::KEY_AMOUNT] += $itemAppliedTax->getAmount(); - $orderAppliedTaxesData[$code][AppliedTax::KEY_BASE_AMOUNT] += $itemAppliedTax->getBaseAmount(); + $orderAppliedTaxesData[$code][Tax::KEY_AMOUNT] += $itemAppliedTax->getAmount(); + $orderAppliedTaxesData[$code][Tax::KEY_BASE_AMOUNT] += $itemAppliedTax->getBaseAmount(); } } } foreach ($orderAppliedTaxesData as $orderAppliedTaxData) { $orderAppliedTaxes[] = $appliedTaxDataObjectFactory->create() - ->setCode($orderAppliedTaxData[AppliedTax::KEY_CODE]) - ->setTitle($orderAppliedTaxData[AppliedTax::KEY_TITLE]) - ->setPercent($orderAppliedTaxData[AppliedTax::KEY_PERCENT]) - ->setAmount($orderAppliedTaxData[AppliedTax::KEY_AMOUNT]) - ->setBaseAmount($orderAppliedTaxData[AppliedTax::KEY_BASE_AMOUNT]); + ->setCode($orderAppliedTaxData[Tax::KEY_CODE]) + ->setTitle($orderAppliedTaxData[Tax::KEY_TITLE]) + ->setPercent($orderAppliedTaxData[Tax::KEY_PERCENT]) + ->setAmount($orderAppliedTaxData[Tax::KEY_AMOUNT]) + ->setBaseAmount($orderAppliedTaxData[Tax::KEY_BASE_AMOUNT]); } return $orderAppliedTaxes; } diff --git a/app/code/Magento/Tax/Model/Sales/Quote/ItemDetails.php b/app/code/Magento/Tax/Model/Sales/Quote/ItemDetails.php index 71d18024ea5f1a199b99ff3811fa4d82d7009ed7..cd893b122f89381b05baa4b5cc41e59d120bd40b 100644 --- a/app/code/Magento/Tax/Model/Sales/Quote/ItemDetails.php +++ b/app/code/Magento/Tax/Model/Sales/Quote/ItemDetails.php @@ -13,12 +13,28 @@ use Magento\Tax\Api\Data\QuoteDetailsItemInterface; */ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_CODE = 'code'; + const KEY_TYPE = 'type'; + const KEY_TAX_CLASS_KEY = 'tax_class_key'; + const KEY_UNIT_PRICE = 'unit_price'; + const KEY_QUANTITY = 'quantity'; + const KEY_TAX_INCLUDED = 'tax_included'; + const KEY_SHORT_DESCRIPTION = 'short_description'; + const KEY_DISCOUNT_AMOUNT = 'discount_amount'; + const KEY_PARENT_CODE = 'parent_code'; + const KEY_ASSOCIATED_ITEM_CODE = 'associated_item_code'; + const KEY_TAX_CLASS_ID = 'tax_class_id'; + /**#@-*/ + /** * {@inheritdoc} */ public function getCode() { - return $this->getData(QuoteDetailsItemInterface::KEY_CODE); + return $this->getData(self::KEY_CODE); } /** @@ -26,7 +42,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getType() { - return $this->getData(QuoteDetailsItemInterface::KEY_TYPE); + return $this->getData(self::KEY_TYPE); } /** @@ -34,7 +50,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getTaxClassKey() { - return $this->getData(QuoteDetailsItemInterface::KEY_TAX_CLASS_KEY); + return $this->getData(self::KEY_TAX_CLASS_KEY); } /** @@ -42,7 +58,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getUnitPrice() { - return $this->getData(QuoteDetailsItemInterface::KEY_UNIT_PRICE); + return $this->getData(self::KEY_UNIT_PRICE); } /** @@ -50,7 +66,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getQuantity() { - return $this->getData(QuoteDetailsItemInterface::KEY_QUANTITY); + return $this->getData(self::KEY_QUANTITY); } /** @@ -58,7 +74,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getTaxIncluded() { - return $this->getData(QuoteDetailsItemInterface::KEY_TAX_INCLUDED); + return $this->getData(self::KEY_TAX_INCLUDED); } /** @@ -66,7 +82,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getShortDescription() { - return $this->getData(QuoteDetailsItemInterface::KEY_SHORT_DESCRIPTION); + return $this->getData(self::KEY_SHORT_DESCRIPTION); } /** @@ -74,7 +90,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getDiscountAmount() { - return $this->getData(QuoteDetailsItemInterface::KEY_DISCOUNT_AMOUNT); + return $this->getData(self::KEY_DISCOUNT_AMOUNT); } /** @@ -82,7 +98,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getParentCode() { - return $this->getData(QuoteDetailsItemInterface::KEY_PARENT_CODE); + return $this->getData(self::KEY_PARENT_CODE); } /** @@ -90,7 +106,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getAssociatedItemCode() { - return $this->getData(QuoteDetailsItemInterface::KEY_ASSOCIATED_ITEM_CODE); + return $this->getData(self::KEY_ASSOCIATED_ITEM_CODE); } /** @@ -98,7 +114,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function getTaxClassId() { - return $this->getData(QuoteDetailsItemInterface::KEY_TAX_CLASS_ID); + return $this->getData(self::KEY_TAX_CLASS_ID); } /** @@ -109,7 +125,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setCode($code) { - return $this->setData(QuoteDetailsItemInterface::KEY_CODE, $code); + return $this->setData(self::KEY_CODE, $code); } /** @@ -120,7 +136,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setType($type) { - return $this->setData(QuoteDetailsItemInterface::KEY_TYPE, $type); + return $this->setData(self::KEY_TYPE, $type); } /** @@ -131,7 +147,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setTaxClassKey(\Magento\Tax\Api\Data\TaxClassKeyInterface $taxClassKey = null) { - return $this->setData(QuoteDetailsItemInterface::KEY_TAX_CLASS_KEY, $taxClassKey); + return $this->setData(self::KEY_TAX_CLASS_KEY, $taxClassKey); } /** @@ -142,7 +158,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setUnitPrice($unitPrice) { - return $this->setData(QuoteDetailsItemInterface::KEY_UNIT_PRICE, $unitPrice); + return $this->setData(self::KEY_UNIT_PRICE, $unitPrice); } /** @@ -153,7 +169,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setQuantity($quantity) { - return $this->setData(QuoteDetailsItemInterface::KEY_QUANTITY, $quantity); + return $this->setData(self::KEY_QUANTITY, $quantity); } /** @@ -164,7 +180,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setIsTaxIncluded($isTaxIncluded) { - return $this->setData(QuoteDetailsItemInterface::KEY_TAX_INCLUDED, $isTaxIncluded); + return $this->setData(self::KEY_TAX_INCLUDED, $isTaxIncluded); } /** @@ -175,7 +191,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setShortDescription($shortDescription) { - return $this->setData(QuoteDetailsItemInterface::KEY_SHORT_DESCRIPTION, $shortDescription); + return $this->setData(self::KEY_SHORT_DESCRIPTION, $shortDescription); } /** @@ -186,7 +202,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setDiscountAmount($discountAmount) { - return $this->setData(QuoteDetailsItemInterface::KEY_DISCOUNT_AMOUNT, $discountAmount); + return $this->setData(self::KEY_DISCOUNT_AMOUNT, $discountAmount); } /** @@ -197,7 +213,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setParentCode($parentCode) { - return $this->setData(QuoteDetailsItemInterface::KEY_PARENT_CODE, $parentCode); + return $this->setData(self::KEY_PARENT_CODE, $parentCode); } /** @@ -208,7 +224,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setAssociatedItemCode($associatedItemCode) { - return $this->setData(QuoteDetailsItemInterface::KEY_ASSOCIATED_ITEM_CODE, $associatedItemCode); + return $this->setData(self::KEY_ASSOCIATED_ITEM_CODE, $associatedItemCode); } /** @@ -219,7 +235,7 @@ class ItemDetails extends AbstractExtensibleModel implements QuoteDetailsItemInt */ public function setTaxClassId($taxClassId) { - return $this->setData(QuoteDetailsItemInterface::KEY_TAX_CLASS_ID, $taxClassId); + return $this->setData(self::KEY_TAX_CLASS_ID, $taxClassId); } /** diff --git a/app/code/Magento/Tax/Model/Sales/Quote/QuoteDetails.php b/app/code/Magento/Tax/Model/Sales/Quote/QuoteDetails.php index 1ef369ba40d82dfb3655926be7970e003892a152..1569e8496bd0cb9417b6f0609df658f06f21a0ed 100644 --- a/app/code/Magento/Tax/Model/Sales/Quote/QuoteDetails.php +++ b/app/code/Magento/Tax/Model/Sales/Quote/QuoteDetails.php @@ -13,12 +13,23 @@ use Magento\Tax\Api\Data\QuoteDetailsInterface; */ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_BILLING_ADDRESS = 'billing_address'; + const KEY_SHIPPING_ADDRESS = 'shipping_address'; + const KEY_CUSTOMER_TAX_CLASS_KEY = 'customer_tax_class_key'; + const KEY_ITEMS = 'items'; + const KEY_CUSTOMER_TAX_CLASS_ID = 'customer_tax_class_id'; + const KEY_CUSTOMER_ID = 'customer_id'; + /**#@-*/ + /** * {@inheritdoc} */ public function getBillingAddress() { - return $this->getData(QuoteDetailsInterface::KEY_BILLING_ADDRESS); + return $this->getData(self::KEY_BILLING_ADDRESS); } /** @@ -26,7 +37,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function getShippingAddress() { - return $this->getData(QuoteDetailsInterface::KEY_SHIPPING_ADDRESS); + return $this->getData(self::KEY_SHIPPING_ADDRESS); } /** @@ -34,7 +45,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function getCustomerTaxClassKey() { - return $this->getData(QuoteDetailsInterface::KEY_CUSTOMER_TAX_CLASS_KEY); + return $this->getData(self::KEY_CUSTOMER_TAX_CLASS_KEY); } /** @@ -42,7 +53,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function getCustomerId() { - return $this->getData(QuoteDetailsInterface::KEY_CUSTOMER_ID); + return $this->getData(self::KEY_CUSTOMER_ID); } /** @@ -50,7 +61,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function getItems() { - return $this->getData(QuoteDetailsInterface::KEY_ITEMS); + return $this->getData(self::KEY_ITEMS); } /** @@ -58,7 +69,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function getCustomerTaxClassId() { - return $this->getData(QuoteDetailsInterface::CUSTOMER_TAX_CLASS_ID); + return $this->getData(self::KEY_CUSTOMER_TAX_CLASS_ID); } /** @@ -69,7 +80,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function setBillingAddress(\Magento\Customer\Api\Data\AddressInterface $billingAddress = null) { - return $this->setData(QuoteDetailsInterface::KEY_BILLING_ADDRESS, $billingAddress); + return $this->setData(self::KEY_BILLING_ADDRESS, $billingAddress); } /** @@ -80,7 +91,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function setShippingAddress(\Magento\Customer\Api\Data\AddressInterface $shippingAddress = null) { - return $this->setData(QuoteDetailsInterface::KEY_SHIPPING_ADDRESS, $shippingAddress); + return $this->setData(self::KEY_SHIPPING_ADDRESS, $shippingAddress); } /** @@ -91,7 +102,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function setCustomerTaxClassKey(\Magento\Tax\Api\Data\TaxClassKeyInterface $customerTaxClassKey = null) { - return $this->setData(QuoteDetailsInterface::KEY_CUSTOMER_TAX_CLASS_KEY, $customerTaxClassKey); + return $this->setData(self::KEY_CUSTOMER_TAX_CLASS_KEY, $customerTaxClassKey); } /** @@ -102,7 +113,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function setCustomerId($customerId) { - return $this->setData(QuoteDetailsInterface::KEY_CUSTOMER_ID, $customerId); + return $this->setData(self::KEY_CUSTOMER_ID, $customerId); } /** @@ -113,7 +124,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function setItems(array $items = null) { - return $this->setData(QuoteDetailsInterface::KEY_ITEMS, $items); + return $this->setData(self::KEY_ITEMS, $items); } /** @@ -124,7 +135,7 @@ class QuoteDetails extends AbstractExtensibleModel implements QuoteDetailsInterf */ public function setCustomerTaxClassId($customerTaxClassId) { - return $this->setData(QuoteDetailsInterface::CUSTOMER_TAX_CLASS_ID, $customerTaxClassId); + return $this->setData(self::KEY_CUSTOMER_TAX_CLASS_ID, $customerTaxClassId); } /** diff --git a/app/code/Magento/Tax/Model/TaxCalculation.php b/app/code/Magento/Tax/Model/TaxCalculation.php index fdbc6cb724bfe1bf27df13375ba11d8ff29af87e..579ee5519899603976a08b1aeb874a59f1f8d774 100644 --- a/app/code/Magento/Tax/Model/TaxCalculation.php +++ b/app/code/Magento/Tax/Model/TaxCalculation.php @@ -6,19 +6,19 @@ namespace Magento\Tax\Model; -use Magento\Tax\Api\Data\TaxDetailsInterface; +use Magento\Tax\Api\TaxCalculationInterface; +use Magento\Tax\Api\TaxClassManagementInterface; use Magento\Tax\Api\Data\TaxDetailsItemInterface; use Magento\Tax\Api\Data\QuoteDetailsItemInterface; use Magento\Tax\Api\Data\TaxDetailsInterfaceFactory; use Magento\Tax\Api\Data\TaxDetailsItemInterfaceFactory; -use Magento\Tax\Api\Data\AppliedTaxRateInterface; -use Magento\Tax\Api\Data\AppliedTaxInterface; -use Magento\Tax\Api\TaxClassManagementInterface; +use Magento\Tax\Model\Calculation\AbstractCalculator; use Magento\Tax\Model\Calculation\CalculatorFactory; use Magento\Tax\Model\Config; -use Magento\Tax\Model\Calculation\AbstractCalculator; +use Magento\Tax\Model\TaxDetails\AppliedTax; +use Magento\Tax\Model\TaxDetails\AppliedTaxRate; +use Magento\Tax\Model\TaxDetails\TaxDetails; use Magento\Store\Model\StoreManagerInterface; -use Magento\Tax\Api\TaxCalculationInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -142,11 +142,11 @@ class TaxCalculation implements TaxCalculationInterface // initial TaxDetails data $taxDetailsData = [ - TaxDetailsInterface::KEY_SUBTOTAL => 0.0, - TaxDetailsInterface::KEY_TAX_AMOUNT => 0.0, - TaxDetailsInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT => 0.0, - TaxDetailsInterface::KEY_APPLIED_TAXES => [], - TaxDetailsInterface::KEY_ITEMS => [], + TaxDetails::KEY_SUBTOTAL => 0.0, + TaxDetails::KEY_TAX_AMOUNT => 0.0, + TaxDetails::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT => 0.0, + TaxDetails::KEY_APPLIED_TAXES => [], + TaxDetails::KEY_ITEMS => [], ]; $items = $quoteDetails->getItems(); if (empty($items)) { @@ -327,21 +327,21 @@ class TaxCalculation implements TaxCalculationInterface */ protected function aggregateItemData($taxDetailsData, TaxDetailsItemInterface $item) { - $taxDetailsData[TaxDetailsInterface::KEY_SUBTOTAL] - = $taxDetailsData[TaxDetailsInterface::KEY_SUBTOTAL] + $item->getRowTotal(); + $taxDetailsData[TaxDetails::KEY_SUBTOTAL] + = $taxDetailsData[TaxDetails::KEY_SUBTOTAL] + $item->getRowTotal(); - $taxDetailsData[TaxDetailsInterface::KEY_TAX_AMOUNT] - = $taxDetailsData[TaxDetailsInterface::KEY_TAX_AMOUNT] + $item->getRowTax(); + $taxDetailsData[TaxDetails::KEY_TAX_AMOUNT] + = $taxDetailsData[TaxDetails::KEY_TAX_AMOUNT] + $item->getRowTax(); - $taxDetailsData[TaxDetailsInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT] = - $taxDetailsData[TaxDetailsInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT] + $taxDetailsData[TaxDetails::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT] = + $taxDetailsData[TaxDetails::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT] + $item->getDiscountTaxCompensationAmount(); $itemAppliedTaxes = $item->getAppliedTaxes(); if ($itemAppliedTaxes === null) { return $taxDetailsData; } - $appliedTaxes = $taxDetailsData[TaxDetailsInterface::KEY_APPLIED_TAXES]; + $appliedTaxes = $taxDetailsData[TaxDetails::KEY_APPLIED_TAXES]; foreach ($itemAppliedTaxes as $taxId => $itemAppliedTax) { if (!isset($appliedTaxes[$taxId])) { //convert rate data object to array @@ -349,23 +349,23 @@ class TaxCalculation implements TaxCalculationInterface $rateDataObjects = $itemAppliedTax->getRates(); foreach ($rateDataObjects as $rateDataObject) { $rates[$rateDataObject->getCode()] = [ - AppliedTaxRateInterface::KEY_CODE => $rateDataObject->getCode(), - AppliedTaxRateInterface::KEY_TITLE => $rateDataObject->getTitle(), - AppliedTaxRateInterface::KEY_PERCENT => $rateDataObject->getPercent(), + AppliedTaxRate::KEY_CODE => $rateDataObject->getCode(), + AppliedTaxRate::KEY_TITLE => $rateDataObject->getTitle(), + AppliedTaxRate::KEY_PERCENT => $rateDataObject->getPercent(), ]; } $appliedTaxes[$taxId] = [ - AppliedTaxInterface::KEY_AMOUNT => $itemAppliedTax->getAmount(), - AppliedTaxInterface::KEY_PERCENT => $itemAppliedTax->getPercent(), - AppliedTaxInterface::KEY_RATES => $rates, - AppliedTaxInterface::KEY_TAX_RATE_KEY => $itemAppliedTax->getTaxRateKey(), + AppliedTax::KEY_AMOUNT => $itemAppliedTax->getAmount(), + AppliedTax::KEY_PERCENT => $itemAppliedTax->getPercent(), + AppliedTax::KEY_RATES => $rates, + AppliedTax::KEY_TAX_RATE_KEY => $itemAppliedTax->getTaxRateKey(), ]; } else { - $appliedTaxes[$taxId][AppliedTaxInterface::KEY_AMOUNT] += $itemAppliedTax->getAmount(); + $appliedTaxes[$taxId][AppliedTax::KEY_AMOUNT] += $itemAppliedTax->getAmount(); } } - $taxDetailsData[TaxDetailsInterface::KEY_APPLIED_TAXES] = $appliedTaxes; + $taxDetailsData[TaxDetails::KEY_APPLIED_TAXES] = $appliedTaxes; return $taxDetailsData; } diff --git a/app/code/Magento/Tax/Model/TaxClass/Key.php b/app/code/Magento/Tax/Model/TaxClass/Key.php index 085b018aa88f7ad8ba4ef5a36fea99c31f6ded54..c882d2dae170cfa9589909859f8b0eb995a41d01 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Key.php +++ b/app/code/Magento/Tax/Model/TaxClass/Key.php @@ -13,12 +13,19 @@ use Magento\Tax\Api\Data\TaxClassKeyInterface; */ class Key extends AbstractExtensibleModel implements TaxClassKeyInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_TYPE = 'type'; + const KEY_VALUE = 'value'; + /**#@-*/ + /** * {@inheritdoc} */ public function getType() { - return $this->getData(TaxClassKeyInterface::KEY_TYPE); + return $this->getData(self::KEY_TYPE); } /** @@ -26,7 +33,7 @@ class Key extends AbstractExtensibleModel implements TaxClassKeyInterface */ public function getValue() { - return $this->getData(TaxClassKeyInterface::KEY_VALUE); + return $this->getData(self::KEY_VALUE); } /** @@ -37,7 +44,7 @@ class Key extends AbstractExtensibleModel implements TaxClassKeyInterface */ public function setType($type) { - return $this->setData(TaxClassKeyInterface::KEY_TYPE, $type); + return $this->setData(self::KEY_TYPE, $type); } /** @@ -48,7 +55,7 @@ class Key extends AbstractExtensibleModel implements TaxClassKeyInterface */ public function setValue($value) { - return $this->setData(TaxClassKeyInterface::KEY_VALUE, $value); + return $this->setData(self::KEY_VALUE, $value); } /** diff --git a/app/code/Magento/Tax/Model/TaxClass/Management.php b/app/code/Magento/Tax/Model/TaxClass/Management.php index 679a054b62314f379cfbc94ec0b0633a1142c059..eb7871c1086c22efe4e988254490bf02abdebf48 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Management.php +++ b/app/code/Magento/Tax/Model/TaxClass/Management.php @@ -9,8 +9,8 @@ namespace Magento\Tax\Model\TaxClass; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Tax\Api\Data\TaxClassInterface; use Magento\Tax\Api\Data\TaxClassKeyInterface; +use Magento\Tax\Model\ClassModel; class Management implements \Magento\Tax\Api\TaxClassManagementInterface { @@ -61,10 +61,10 @@ class Management implements \Magento\Tax\Api\TaxClassManagementInterface return $taxClassKey->getValue(); case TaxClassKeyInterface::TYPE_NAME: $searchCriteria = $this->searchCriteriaBuilder->addFilter( - [$this->filterBuilder->setField(TaxClassInterface::KEY_TYPE)->setValue($taxClassType)->create()] + [$this->filterBuilder->setField(ClassModel::KEY_TYPE)->setValue($taxClassType)->create()] )->addFilter( [ - $this->filterBuilder->setField(TaxClassInterface::KEY_NAME) + $this->filterBuilder->setField(ClassModel::KEY_NAME) ->setValue($taxClassKey->getValue()) ->create(), ] diff --git a/app/code/Magento/Tax/Model/TaxClass/Repository.php b/app/code/Magento/Tax/Model/TaxClass/Repository.php index a0fc6fe76d46ec8718a7cccf2af8a44068b73425..01dd656b0d5e51d5b64e22c8fd4d80e937d19e2b 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Repository.php +++ b/app/code/Magento/Tax/Model/TaxClass/Repository.php @@ -15,8 +15,8 @@ use Magento\Framework\Api\SortOrder; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\LocalizedException as ModelException; -use Magento\Tax\Api\Data\TaxClassInterface; use Magento\Tax\Api\TaxClassManagementInterface; +use Magento\Tax\Model\ClassModel; use Magento\Tax\Model\ClassModelRegistry; use Magento\Tax\Model\Resource\TaxClass\Collection as TaxClassCollection; use Magento\Tax\Model\Resource\TaxClass\CollectionFactory as TaxClassCollectionFactory; @@ -164,19 +164,19 @@ class Repository implements \Magento\Tax\Api\TaxClassRepositoryInterface $exception = new InputException(); if (!\Zend_Validate::is(trim($taxClass->getClassName()), 'NotEmpty')) { - $exception->addError(__(InputException::REQUIRED_FIELD, ['fieldName' => TaxClassInterface::KEY_NAME])); + $exception->addError(__(InputException::REQUIRED_FIELD, ['fieldName' => ClassModel::KEY_NAME])); } $classType = $taxClass->getClassType(); if (!\Zend_Validate::is(trim($classType), 'NotEmpty')) { - $exception->addError(__(InputException::REQUIRED_FIELD, ['fieldName' => TaxClassInterface::KEY_TYPE])); + $exception->addError(__(InputException::REQUIRED_FIELD, ['fieldName' => ClassModel::KEY_TYPE])); } elseif ($classType !== TaxClassManagementInterface::TYPE_CUSTOMER && $classType !== TaxClassManagementInterface::TYPE_PRODUCT ) { $exception->addError( __( InputException::INVALID_FIELD_VALUE, - ['fieldName' => TaxClassInterface::KEY_TYPE, 'value' => $classType] + ['fieldName' => ClassModel::KEY_TYPE, 'value' => $classType] ) ); } diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php index 4a52c81b669fb5a3a13b775ab60686f18ecb5c99..ca0dd21abdd84a2714adf6c8eb26aa89c83584de 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php +++ b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php @@ -8,7 +8,7 @@ namespace Magento\Tax\Model\TaxClass\Source; use Magento\Framework\Exception\StateException; use Magento\Tax\Api\TaxClassManagementInterface; -use Magento\Tax\Api\Data\TaxClassInterface as TaxClass; +use Magento\Tax\Model\ClassModel; /** * Customer tax class source model. @@ -57,7 +57,7 @@ class Customer extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource { if (empty($this->_options)) { $options = []; - $filter = $this->filterBuilder->setField(TaxClass::KEY_TYPE) + $filter = $this->filterBuilder->setField(ClassModel::KEY_TYPE) ->setValue(TaxClassManagementInterface::TYPE_CUSTOMER) ->create(); $searchCriteria = $this->searchCriteriaBuilder->addFilter([$filter])->create(); diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Product.php b/app/code/Magento/Tax/Model/TaxClass/Source/Product.php index bf8711f93228abcfec3c8c6836ff0dd3847a4b23..37844ab57076c71cfc5fb8c57010de4db1fe5444 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Source/Product.php +++ b/app/code/Magento/Tax/Model/TaxClass/Source/Product.php @@ -7,8 +7,8 @@ namespace Magento\Tax\Model\TaxClass\Source; use Magento\Framework\DB\Ddl\Table; -use Magento\Tax\Api\Data\TaxClassInterface as TaxClass; use Magento\Tax\Api\TaxClassManagementInterface; +use Magento\Tax\Model\ClassModel; /** * Product tax class source model. @@ -68,7 +68,7 @@ class Product extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource { if (!$this->_options) { $filter = $this->_filterBuilder - ->setField(TaxClass::KEY_TYPE) + ->setField(ClassModel::KEY_TYPE) ->setValue(TaxClassManagementInterface::TYPE_PRODUCT) ->create(); $searchCriteria = $this->_searchCriteriaBuilder->addFilter([$filter])->create(); diff --git a/app/code/Magento/Tax/Model/TaxDetails/AppliedTax.php b/app/code/Magento/Tax/Model/TaxDetails/AppliedTax.php index 79265cacbc0c8615b0989d9deae57cb4ab6ee405..c5857168feddd83a0280449aadd5bc05c831838e 100644 --- a/app/code/Magento/Tax/Model/TaxDetails/AppliedTax.php +++ b/app/code/Magento/Tax/Model/TaxDetails/AppliedTax.php @@ -13,12 +13,21 @@ use Magento\Tax\Api\Data\AppliedTaxInterface; */ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_TAX_RATE_KEY = 'tax_rate_key'; + const KEY_PERCENT = 'percent'; + const KEY_AMOUNT = 'amount'; + const KEY_RATES = 'rates'; + /**#@-*/ + /** * {@inheritdoc} */ public function getTaxRateKey() { - return $this->getData(AppliedTaxInterface::KEY_TAX_RATE_KEY); + return $this->getData(self::KEY_TAX_RATE_KEY); } /** @@ -26,7 +35,7 @@ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface */ public function getPercent() { - return $this->getData(AppliedTaxInterface::KEY_PERCENT); + return $this->getData(self::KEY_PERCENT); } /** @@ -34,7 +43,7 @@ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface */ public function getAmount() { - return $this->getData(AppliedTaxInterface::KEY_AMOUNT); + return $this->getData(self::KEY_AMOUNT); } /** @@ -42,7 +51,7 @@ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface */ public function getRates() { - return $this->getData(AppliedTaxInterface::KEY_RATES); + return $this->getData(self::KEY_RATES); } /** @@ -53,7 +62,7 @@ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface */ public function setTaxRateKey($taxRateKey) { - return $this->setData(AppliedTaxInterface::KEY_TAX_RATE_KEY, $taxRateKey); + return $this->setData(self::KEY_TAX_RATE_KEY, $taxRateKey); } /** @@ -64,7 +73,7 @@ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface */ public function setPercent($percent) { - return $this->setData(AppliedTaxInterface::KEY_PERCENT, $percent); + return $this->setData(self::KEY_PERCENT, $percent); } /** @@ -75,7 +84,7 @@ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface */ public function setAmount($amount) { - return $this->setData(AppliedTaxInterface::KEY_AMOUNT, $amount); + return $this->setData(self::KEY_AMOUNT, $amount); } /** @@ -86,7 +95,7 @@ class AppliedTax extends AbstractExtensibleModel implements AppliedTaxInterface */ public function setRates(array $rates = null) { - return $this->setData(AppliedTaxInterface::KEY_RATES, $rates); + return $this->setData(self::KEY_RATES, $rates); } /** diff --git a/app/code/Magento/Tax/Model/TaxDetails/AppliedTaxRate.php b/app/code/Magento/Tax/Model/TaxDetails/AppliedTaxRate.php index 8cd44cb70e0e36de4ebe281b05e439e18be8312d..a04aed56a7f4a8b6224f628d9786d98a136821f3 100644 --- a/app/code/Magento/Tax/Model/TaxDetails/AppliedTaxRate.php +++ b/app/code/Magento/Tax/Model/TaxDetails/AppliedTaxRate.php @@ -13,12 +13,20 @@ use Magento\Tax\Api\Data\AppliedTaxRateInterface; */ class AppliedTaxRate extends AbstractExtensibleModel implements AppliedTaxRateInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_CODE = 'code'; + const KEY_TITLE = 'title'; + const KEY_PERCENT = 'percent'; + /**#@-*/ + /** * {@inheritdoc} */ public function getCode() { - return $this->getData(AppliedTaxRateInterface::KEY_CODE); + return $this->getData(self::KEY_CODE); } /** @@ -26,7 +34,7 @@ class AppliedTaxRate extends AbstractExtensibleModel implements AppliedTaxRateIn */ public function getTitle() { - return $this->getData(AppliedTaxRateInterface::KEY_TITLE); + return $this->getData(self::KEY_TITLE); } /** @@ -34,7 +42,7 @@ class AppliedTaxRate extends AbstractExtensibleModel implements AppliedTaxRateIn */ public function getPercent() { - return $this->getData(AppliedTaxRateInterface::KEY_PERCENT); + return $this->getData(self::KEY_PERCENT); } /** @@ -45,7 +53,7 @@ class AppliedTaxRate extends AbstractExtensibleModel implements AppliedTaxRateIn */ public function setCode($code) { - return $this->setData(AppliedTaxRateInterface::KEY_CODE, $code); + return $this->setData(self::KEY_CODE, $code); } /** @@ -56,7 +64,7 @@ class AppliedTaxRate extends AbstractExtensibleModel implements AppliedTaxRateIn */ public function setTitle($title) { - return $this->setData(AppliedTaxRateInterface::KEY_TITLE, $title); + return $this->setData(self::KEY_TITLE, $title); } /** @@ -67,7 +75,7 @@ class AppliedTaxRate extends AbstractExtensibleModel implements AppliedTaxRateIn */ public function setPercent($percent) { - return $this->setData(AppliedTaxRateInterface::KEY_PERCENT, $percent); + return $this->setData(self::KEY_PERCENT, $percent); } /** diff --git a/app/code/Magento/Tax/Model/TaxDetails/ItemDetails.php b/app/code/Magento/Tax/Model/TaxDetails/ItemDetails.php index 9ba71b43dedf1c2bf676436e6a3754e4f168d69f..d4f1628fbdbb8f4921e1162f01e23bd68aa94223 100644 --- a/app/code/Magento/Tax/Model/TaxDetails/ItemDetails.php +++ b/app/code/Magento/Tax/Model/TaxDetails/ItemDetails.php @@ -13,12 +13,30 @@ use Magento\Tax\Api\Data\TaxDetailsItemInterface; */ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_CODE = 'code'; + const KEY_TYPE = 'type'; + const KEY_TAX_PERCENT = 'tax_percent'; + const KEY_PRICE = 'price'; + const KEY_PRICE_INCL_TAX = 'price_incl_tax'; + const KEY_ROW_TOTAL = 'row_total'; + const KEY_ROW_TOTAL_INCL_TAX = 'row_total_incl_tax'; + const KEY_ROW_TAX = 'row_tax'; + const KEY_TAXABLE_AMOUNT = 'taxable_amount'; + const KEY_DISCOUNT_AMOUNT = 'discount_amount'; + const KEY_APPLIED_TAXES = 'applied_taxes'; + const KEY_ASSOCIATED_ITEM_CODE = 'associated_item_code'; + const KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; + /**#@-*/ + /** * {@inheritdoc} */ public function getCode() { - return $this->getData(TaxDetailsItemInterface::KEY_CODE); + return $this->getData(self::KEY_CODE); } /** @@ -26,7 +44,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getType() { - return $this->getData(TaxDetailsItemInterface::KEY_TYPE); + return $this->getData(self::KEY_TYPE); } /** @@ -34,7 +52,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getTaxPercent() { - return $this->getData(TaxDetailsItemInterface::KEY_TAX_PERCENT); + return $this->getData(self::KEY_TAX_PERCENT); } /** @@ -42,7 +60,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getPrice() { - return $this->getData(TaxDetailsItemInterface::KEY_PRICE); + return $this->getData(self::KEY_PRICE); } /** @@ -50,7 +68,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getPriceInclTax() { - return $this->getData(TaxDetailsItemInterface::KEY_PRICE_INCL_TAX); + return $this->getData(self::KEY_PRICE_INCL_TAX); } /** @@ -58,7 +76,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getRowTotal() { - return $this->getData(TaxDetailsItemInterface::KEY_ROW_TOTAL); + return $this->getData(self::KEY_ROW_TOTAL); } /** @@ -66,7 +84,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getRowTotalInclTax() { - return $this->getData(TaxDetailsItemInterface::KEY_ROW_TOTAL_INCL_TAX); + return $this->getData(self::KEY_ROW_TOTAL_INCL_TAX); } /** @@ -74,7 +92,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getRowTax() { - return $this->getData(TaxDetailsItemInterface::KEY_ROW_TAX); + return $this->getData(self::KEY_ROW_TAX); } /** @@ -82,7 +100,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getTaxableAmount() { - return $this->getData(TaxDetailsItemInterface::KEY_TAXABLE_AMOUNT); + return $this->getData(self::KEY_TAXABLE_AMOUNT); } /** @@ -90,7 +108,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getDiscountAmount() { - return $this->getData(TaxDetailsItemInterface::KEY_DISCOUNT_AMOUNT); + return $this->getData(self::KEY_DISCOUNT_AMOUNT); } /** @@ -98,7 +116,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getDiscountTaxCompensationAmount() { - return $this->getData(TaxDetailsItemInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT); + return $this->getData(self::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -106,7 +124,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getAppliedTaxes() { - return $this->getData(TaxDetailsItemInterface::KEY_APPLIED_TAXES); + return $this->getData(self::KEY_APPLIED_TAXES); } /** @@ -114,7 +132,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function getAssociatedItemCode() { - return $this->getData(TaxDetailsItemInterface::KEY_ASSOCIATED_ITEM_CODE); + return $this->getData(self::KEY_ASSOCIATED_ITEM_CODE); } /** @@ -125,7 +143,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setCode($code) { - return $this->setData(TaxDetailsItemInterface::KEY_CODE, $code); + return $this->setData(self::KEY_CODE, $code); } /** @@ -136,7 +154,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setType($type) { - return $this->setData(TaxDetailsItemInterface::KEY_TYPE, $type); + return $this->setData(self::KEY_TYPE, $type); } /** @@ -147,7 +165,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setTaxPercent($taxPercent) { - return $this->setData(TaxDetailsItemInterface::KEY_TAX_PERCENT, $taxPercent); + return $this->setData(self::KEY_TAX_PERCENT, $taxPercent); } /** @@ -158,7 +176,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setPrice($price) { - return $this->setData(TaxDetailsItemInterface::KEY_PRICE, $price); + return $this->setData(self::KEY_PRICE, $price); } /** @@ -169,7 +187,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setPriceInclTax($priceInclTax) { - return $this->setData(TaxDetailsItemInterface::KEY_PRICE_INCL_TAX, $priceInclTax); + return $this->setData(self::KEY_PRICE_INCL_TAX, $priceInclTax); } /** @@ -180,7 +198,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setRowTotal($rowTotal) { - return $this->setData(TaxDetailsItemInterface::KEY_ROW_TOTAL, $rowTotal); + return $this->setData(self::KEY_ROW_TOTAL, $rowTotal); } /** @@ -191,7 +209,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setRowTotalInclTax($rowTotalInclTax) { - return $this->setData(TaxDetailsItemInterface::KEY_ROW_TOTAL_INCL_TAX, $rowTotalInclTax); + return $this->setData(self::KEY_ROW_TOTAL_INCL_TAX, $rowTotalInclTax); } /** @@ -202,7 +220,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setRowTax($rowTax) { - return $this->setData(TaxDetailsItemInterface::KEY_ROW_TAX, $rowTax); + return $this->setData(self::KEY_ROW_TAX, $rowTax); } /** @@ -213,7 +231,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setTaxableAmount($taxableAmount) { - return $this->setData(TaxDetailsItemInterface::KEY_TAXABLE_AMOUNT, $taxableAmount); + return $this->setData(self::KEY_TAXABLE_AMOUNT, $taxableAmount); } /** @@ -224,7 +242,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setDiscountAmount($discountAmount) { - return $this->setData(TaxDetailsItemInterface::KEY_DISCOUNT_AMOUNT, $discountAmount); + return $this->setData(self::KEY_DISCOUNT_AMOUNT, $discountAmount); } /** @@ -236,7 +254,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter public function setDiscountTaxCompensationAmount($discountTaxCompensationAmount) { return $this->setData( - TaxDetailsItemInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT, + self::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT, $discountTaxCompensationAmount ); } @@ -249,7 +267,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setAppliedTaxes(array $appliedTaxes = null) { - return $this->setData(TaxDetailsItemInterface::KEY_APPLIED_TAXES, $appliedTaxes); + return $this->setData(self::KEY_APPLIED_TAXES, $appliedTaxes); } /** @@ -260,7 +278,7 @@ class ItemDetails extends AbstractExtensibleModel implements TaxDetailsItemInter */ public function setAssociatedItemCode($associatedItemCode) { - return $this->setData(TaxDetailsItemInterface::KEY_ASSOCIATED_ITEM_CODE, $associatedItemCode); + return $this->setData(self::KEY_ASSOCIATED_ITEM_CODE, $associatedItemCode); } /** diff --git a/app/code/Magento/Tax/Model/TaxDetails/TaxDetails.php b/app/code/Magento/Tax/Model/TaxDetails/TaxDetails.php index 91f1587c8b575ce08e5f52a0196c724f40917a36..721dedffeb29e43cb8433b1222e9e0059e8a4f7a 100644 --- a/app/code/Magento/Tax/Model/TaxDetails/TaxDetails.php +++ b/app/code/Magento/Tax/Model/TaxDetails/TaxDetails.php @@ -13,12 +13,22 @@ use Magento\Tax\Api\Data\TaxDetailsInterface; */ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface { + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const KEY_SUBTOTAL = 'subtotal'; + const KEY_TAX_AMOUNT = 'tax_amount'; + const KEY_APPLIED_TAXES = 'applied_taxes'; + const KEY_ITEMS = 'items'; + const KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; + /**#@-*/ + /** * {@inheritdoc} */ public function getSubtotal() { - return $this->getData(TaxDetailsInterface::KEY_SUBTOTAL); + return $this->getData(self::KEY_SUBTOTAL); } /** @@ -26,7 +36,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function getTaxAmount() { - return $this->getData(TaxDetailsInterface::KEY_TAX_AMOUNT); + return $this->getData(self::KEY_TAX_AMOUNT); } /** @@ -34,7 +44,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function getDiscountTaxCompensationAmount() { - return $this->getData(TaxDetailsInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT); + return $this->getData(self::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -42,7 +52,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function getAppliedTaxes() { - return $this->getData(TaxDetailsInterface::KEY_APPLIED_TAXES); + return $this->getData(self::KEY_APPLIED_TAXES); } /** @@ -50,7 +60,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function getItems() { - return $this->getData(TaxDetailsInterface::KEY_ITEMS); + return $this->getData(self::KEY_ITEMS); } /** @@ -61,7 +71,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function setSubtotal($subtotal) { - return $this->setData(TaxDetailsInterface::KEY_SUBTOTAL, $subtotal); + return $this->setData(self::KEY_SUBTOTAL, $subtotal); } /** @@ -72,7 +82,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function setTaxAmount($taxAmount) { - return $this->setData(TaxDetailsInterface::KEY_TAX_AMOUNT, $taxAmount); + return $this->setData(self::KEY_TAX_AMOUNT, $taxAmount); } /** @@ -84,7 +94,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface public function setDiscountTaxCompensationAmount($discountTaxCompensationAmount) { return $this->setData( - TaxDetailsInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT, + self::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT, $discountTaxCompensationAmount ); } @@ -97,7 +107,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function setAppliedTaxes(array $appliedTaxes = null) { - return $this->setData(TaxDetailsInterface::KEY_APPLIED_TAXES, $appliedTaxes); + return $this->setData(self::KEY_APPLIED_TAXES, $appliedTaxes); } /** @@ -108,7 +118,7 @@ class TaxDetails extends AbstractExtensibleModel implements TaxDetailsInterface */ public function setItems(array $items = null) { - return $this->setData(TaxDetailsInterface::KEY_ITEMS, $items); + return $this->setData(self::KEY_ITEMS, $items); } /** diff --git a/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Rate/AjaxLoadTest.php b/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Rate/AjaxLoadTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6373e5aa514bf11a2d6174c78e64489bd7d558b0 --- /dev/null +++ b/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Rate/AjaxLoadTest.php @@ -0,0 +1,238 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Tax\Test\Unit\Controller\Adminhtml\Rate; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Exception\NoSuchEntityException; + +/** + * Test for AjaxLoadTest + */ +class AjaxLoadTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\Request\Http + */ + private $request; + + /** + * @var \Magento\Framework\App\Response\Http + */ + private $resultFactory; + + /** + * @var \Magento\Tax\Model\Calculation\RateRepository + */ + private $taxRateRepository; + + /* + * test setup + */ + public function setUp() + { + $this->request = $this->getMockBuilder('\Magento\Framework\App\Request\Http') + ->disableOriginalConstructor() + ->setMethods(['getParam']) + ->getMock(); + + $this->resultFactory = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->taxRateRepository = $this->getMockBuilder('\Magento\Tax\Model\Calculation\RateRepository') + ->disableOriginalConstructor() + ->setMethods(['get']) + ->getMock(); + } + + /** + * Executes the controller action and asserts non exception logic + */ + public function testExecute() + { + $taxRateId=1; + $returnArray=[ + 'tax_calculation_rate_id' => null, + 'tax_country_id' => 'US', + 'tax_region_id' => 2, + 'tax_postcode' => null, + 'code' => 'Tax Rate Code', + 'rate' => 7.5, + 'zip_is_range'=> 0, + 'title[1]' => 'texas', + ]; + $objectManager = new ObjectManager($this); + $rateTitles = [$objectManager->getObject( + '\Magento\Tax\Model\Calculation\Rate\Title', + ['data' => ['store_id' => 1, 'value' => 'texas']] + ) + ]; + $rateMock = $objectManager->getObject( + 'Magento\Tax\Model\Calculation\Rate', + [ + 'data' => + [ + 'tax_country_id' => 'US', + 'tax_region_id' => 2, + 'tax_postcode' => null, + 'rate' => 7.5, + 'code' => 'Tax Rate Code', + 'titles' => $rateTitles, + ], + ] + ); + + $this->request->expects($this->any()) + ->method('getParam') + ->will($this->returnValue($taxRateId)); + + $this->taxRateRepository->expects($this->any()) + ->method('get') + ->with($taxRateId) + ->will($this->returnValue($rateMock)); + + $taxRateConverter = $this->getMockBuilder('\Magento\Tax\Model\Calculation\Rate\Converter') + ->disableOriginalConstructor() + ->getMock(); + + $taxRateConverter->expects($this->any()) + ->method('createArrayFromServiceObject') + ->with($rateMock, true) + ->willReturn($returnArray); + + $jsonObject= $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->setMethods(['setData']) + ->getMock(); + + $jsonObject->expects($this->once()) + ->method('setData') + ->with(['success' => true, 'error_message' => '', 'result'=> + $returnArray, + ]); + + $this->resultFactory->expects($this->any()) + ->method('create') + ->with(\Magento\Framework\Controller\ResultFactory::TYPE_JSON) + ->willReturn($jsonObject); + + $notification = $objectManager->getObject( + 'Magento\Tax\Controller\Adminhtml\Rate\AjaxLoad', + [ + 'taxRateRepository' => $this->taxRateRepository, + 'taxRateConverter' => $taxRateConverter, + 'request' => $this->request, + 'resultFactory' => $this->resultFactory, + ] + ); + + + // No exception thrown + $this->assertSame($jsonObject, $notification->execute()); + + } + + /** + * Check if validation throws a localized catched exception in case of incorrect id + */ + public function testExecuteLocalizedException() + { + $taxRateId=999; + $exceptionMessage='No such entity with taxRateId = '.$taxRateId; + $noSuchEntityEx= new NoSuchEntityException(__($exceptionMessage)); + + $objectManager = new ObjectManager($this); + + $this->request->expects($this->any()) + ->method('getParam') + ->will($this->returnValue($taxRateId)); + + $this->taxRateRepository->expects($this->any()) + ->method('get') + ->with($taxRateId) + ->willThrowException($noSuchEntityEx); + + $jsonObject= $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->setMethods(['setData']) + ->getMock(); + + $jsonObject->expects($this->once()) + ->method('setData') + ->with([ + 'success' => false, + 'error_message' => $exceptionMessage, + ]); + + $this->resultFactory->expects($this->any()) + ->method('create') + ->with(\Magento\Framework\Controller\ResultFactory::TYPE_JSON) + ->willReturn($jsonObject); + + $notification = $objectManager->getObject( + 'Magento\Tax\Controller\Adminhtml\Rate\AjaxLoad', + [ + 'taxRateRepository' => $this->taxRateRepository, + 'request' => $this->request, + 'resultFactory' => $this->resultFactory, + ] + ); + + //exception thrown with catch + $this->assertSame($jsonObject, $notification->execute()); + } + + /** + * Check if validation throws a localized catched exception in case of incorrect id + */ + public function testExecuteException() + { + $taxRateId=999; + $exceptionMessage=__('An error occurred while loading this tax rate.'); + $noSuchEntityEx= new \Exception(); + + $objectManager = new ObjectManager($this); + + $this->request->expects($this->any()) + ->method('getParam') + ->will($this->returnValue($taxRateId)); + + $this->taxRateRepository->expects($this->any()) + ->method('get') + ->with($taxRateId) + ->willThrowException($noSuchEntityEx); + + $jsonObject= $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->setMethods(['setData']) + ->getMock(); + + $jsonObject->expects($this->once()) + ->method('setData') + ->with([ + 'success' => false, + 'error_message' => $exceptionMessage, + ]); + + $this->resultFactory->expects($this->any()) + ->method('create') + ->with(\Magento\Framework\Controller\ResultFactory::TYPE_JSON) + ->willReturn($jsonObject); + + $notification = $objectManager->getObject( + 'Magento\Tax\Controller\Adminhtml\Rate\AjaxLoad', + [ + 'taxRateRepository' => $this->taxRateRepository, + 'request' => $this->request, + 'resultFactory' => $this->resultFactory, + ] + ); + + //exception thrown with catch + $this->assertSame($jsonObject, $notification->execute()); + } +} diff --git a/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php b/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php index 9a649f3d2d5b9ca772e5b3df44d0ed1e69e27757..8714905efc56bc118efd516eb8346ec1e2045ad6 100644 --- a/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php +++ b/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Tax\Test\Unit\Controller\Adminhtml\Tax; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class IgnoreTaxNotificationTest extends \PHPUnit_Framework_TestCase @@ -19,7 +20,7 @@ class IgnoreTaxNotificationTest extends \PHPUnit_Framework_TestCase $cacheTypeList->expects($this->once()) ->method('cleanType') ->with('block_html') - ->will($this->returnValue(null)); + ->willReturn(null); $request = $this->getMockBuilder('\Magento\Framework\App\Request\Http') ->disableOriginalConstructor() @@ -27,12 +28,23 @@ class IgnoreTaxNotificationTest extends \PHPUnit_Framework_TestCase ->getMock(); $request->expects($this->once()) ->method('getParam') - ->will($this->returnValue('tax')); + ->willReturn('tax'); - $response = $this->getMockBuilder('\Magento\Framework\App\Response\Http') + $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') ->disableOriginalConstructor() - ->setMethods(['setRedirect']) ->getMock(); + $resultRedirect->expects($this->once()) + ->method('setRefererUrl') + ->willReturnSelf(); + + $resultFactory = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $resultFactory->expects($this->once()) + ->method('create') + ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT) + ->willReturn($resultRedirect); $config = $this->getMockBuilder('\Magento\Config\Model\Resource\Config') ->disableOriginalConstructor() @@ -40,8 +52,8 @@ class IgnoreTaxNotificationTest extends \PHPUnit_Framework_TestCase ->getMock(); $config->expects($this->once()) ->method('saveConfig') - ->with('tax/notification/ignore_tax', 1, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, 0) - ->will($this->returnValue(null)); + ->with('tax/notification/ignore_tax', 1, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0) + ->willReturn(null); $manager = $this->getMockBuilder('\Magento\Framework\ObjectManagerInterface') ->disableOriginalConstructor() @@ -49,7 +61,7 @@ class IgnoreTaxNotificationTest extends \PHPUnit_Framework_TestCase ->getMock(); $manager->expects($this->any()) ->method('get') - ->will($this->returnValue($config)); + ->willReturn($config); $notification = $objectManager->getObject( 'Magento\Tax\Controller\Adminhtml\Tax\IgnoreTaxNotification', @@ -57,11 +69,11 @@ class IgnoreTaxNotificationTest extends \PHPUnit_Framework_TestCase 'objectManager' => $manager, 'cacheTypeList' => $cacheTypeList, 'request' => $request, - 'response' => $response + 'resultFactory' => $resultFactory ] ); // No exception thrown - $notification->execute(); + $this->assertSame($resultRedirect, $notification->execute()); } } diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/Rate/ConverterTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/Rate/ConverterTest.php index 7fa4b63e75e603558c6a26fe028472552f58fd72..dc4dfcf84c4a377205e513c526e15c427018307c 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/Rate/ConverterTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/Rate/ConverterTest.php @@ -5,7 +5,7 @@ */ namespace Magento\Tax\Test\Unit\Model\Calculation\Rate; -use \Magento\Tax\Model\Calculation\Rate\Converter; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class ConverterTest extends \PHPUnit_Framework_TestCase { @@ -14,9 +14,45 @@ class ConverterTest extends \PHPUnit_Framework_TestCase */ protected $converter; + /** + * @var \Magento\Tax\Api\Data\TaxRateInterfaceFactory + */ + protected $taxRateDataObjectFactory; + + /** + * @var \Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory + */ + protected $taxRateTitleDataObjectFactory; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper + */ + protected $objectManager; + public function setUp() { - $this->converter = new Converter(); + $this->taxRateDataObjectFactory = $this->getMockBuilder( + '\Magento\Tax\Api\Data\TaxRateInterfaceFactory' + ) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->taxRateTitleDataObjectFactory = $this->getMockBuilder( + '\Magento\Tax\Api\Data\TaxRateTitleInterfaceFactory' + ) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->objectManager = new ObjectManager($this); + $this->converter = $this->objectManager->getObject( + 'Magento\Tax\Model\Calculation\Rate\Converter', + [ + 'taxRateDataObjectFactory' => $this->taxRateDataObjectFactory, + 'taxRateTitleDataObjectFactory' => $this->taxRateTitleDataObjectFactory, + ] + ); } public function testCreateTitlesFromServiceObject() @@ -39,4 +75,48 @@ class ConverterTest extends \PHPUnit_Framework_TestCase $this->assertEquals([], $this->converter->createTitleArrayFromServiceObject($taxRateMock)); } + + + public function testCreateArrayFromServiceObject() + { + $taxRateMock = $this->getMock('Magento\Tax\Api\Data\TaxRateInterface'); + $titlesMock = $this->getMock('Magento\Tax\Api\Data\TaxRateTitleInterface'); + + $taxRateMock->expects($this->atLeastOnce())->method('getTitles')->willReturn([$titlesMock]); + $titlesMock->expects($this->atLeastOnce())->method('getStoreId')->willReturn(1); + $titlesMock->expects($this->atLeastOnce())->method('getValue')->willReturn('Value'); + + $this->assertArrayHasKey('title[1]', $this->converter->createArrayFromServiceObject($taxRateMock, true)); + $this->assertArrayHasKey('title', $this->converter->createArrayFromServiceObject($taxRateMock)); + $this->assertTrue(is_array($this->converter->createArrayFromServiceObject($taxRateMock))); + } + + public function testPopulateTaxRateData() + { + $rateTitles = [$this->objectManager->getObject( + '\Magento\Tax\Model\Calculation\Rate\Title', + ['data' => ['store_id' => 1, 'value' => 'texas']] + ) + ]; + $dataArray=[ + 'tax_country_id' => 'US', + 'tax_region_id' => 2, + 'tax_postcode' => null, + 'rate' => 7.5, + 'code' => 'Tax Rate Code', + 'titles' => $rateTitles, + ]; + + $taxRate = $this->objectManager->getObject( + 'Magento\Tax\Model\Calculation\Rate', + [ + 'data' =>$dataArray, + ] + ); + + $this->taxRateDataObjectFactory->expects($this->once())->method('create')->willReturn($taxRate); + + $this->assertSame($taxRate, $this->converter->populateTaxRateData($dataArray)); + $this->assertEquals($taxRate->getTitles(), $rateTitles); + } } diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxCalculationTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxCalculationTest.php index f4bd04f1adf82bf8c77346c6ead678e85bb99f2c..d88ea2756c2e95330fc1a520c2d2a42c8744b259 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/TaxCalculationTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/TaxCalculationTest.php @@ -199,11 +199,11 @@ class TaxCalculationTest extends \PHPUnit_Framework_TestCase $customerId = 100; $taxClassId = 200; $taxDetailsData = [ - \Magento\Tax\Api\Data\TaxDetailsInterface::KEY_SUBTOTAL => 0.0, - \Magento\Tax\Api\Data\TaxDetailsInterface::KEY_TAX_AMOUNT => 0.0, - \Magento\Tax\Api\Data\TaxDetailsInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT => 0.0, - \Magento\Tax\Api\Data\TaxDetailsInterface::KEY_APPLIED_TAXES => [], - \Magento\Tax\Api\Data\TaxDetailsInterface::KEY_ITEMS => [], + \Magento\Tax\Model\TaxDetails\TaxDetails::KEY_SUBTOTAL => 0.0, + \Magento\Tax\Model\TaxDetails\TaxDetails::KEY_TAX_AMOUNT => 0.0, + \Magento\Tax\Model\TaxDetails\TaxDetails::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT => 0.0, + \Magento\Tax\Model\TaxDetails\TaxDetails::KEY_APPLIED_TAXES => [], + \Magento\Tax\Model\TaxDetails\TaxDetails::KEY_ITEMS => [], ]; $quoteDetailsMock = $this->getMock('\Magento\Tax\Api\Data\QuoteDetailsInterface'); diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxClass/ManagementTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxClass/ManagementTest.php index 3ceefb565192b79193555b490f15d159f414024b..de391779d3ec915a2796f3404b84206c024cbdbb 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/TaxClass/ManagementTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/TaxClass/ManagementTest.php @@ -79,8 +79,8 @@ class ManagementTest extends \PHPUnit_Framework_TestCase ->method('setField') ->with( $this->logicalOr( - \Magento\Tax\Api\Data\TaxClassInterface::KEY_TYPE, - \Magento\Tax\Api\Data\TaxClassInterface::KEY_NAME + \Magento\Tax\Model\ClassModel::KEY_TYPE, + \Magento\Tax\Model\ClassModel::KEY_NAME ) )->willReturnSelf(); diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxClass/Source/CustomerTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxClass/Source/CustomerTest.php index 6adec4612fe7b22e96f97bba7dd73119d4a4449c..c36618f8faf5c2a7cdc68b9aab3a16fbe274a5d9 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/TaxClass/Source/CustomerTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/TaxClass/Source/CustomerTest.php @@ -120,7 +120,7 @@ class CustomerTest extends \PHPUnit_Framework_TestCase $this->filterBuilderMock->expects($this->once()) ->method('setField') - ->with(\Magento\Tax\Api\Data\TaxClassInterface::KEY_TYPE) + ->with(\Magento\Tax\Model\ClassModel::KEY_TYPE) ->willReturnSelf(); $this->filterBuilderMock->expects($this->once()) ->method('setValue') diff --git a/app/code/Magento/Tax/composer.json b/app/code/Magento/Tax/composer.json index 27b9422635e75187471b290bb89d920fa9ccb1c5..dd35c3d1f65c9f9890e939efa1acbc2c5022fb64 100644 --- a/app/code/Magento/Tax/composer.json +++ b/app/code/Magento/Tax/composer.json @@ -3,23 +3,23 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-reports": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-config": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-reports": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml b/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml index e1941d06d1d4973744aa9e6cc415e282cc799780..4861e4b3bdc539fe555e6eefa3eaad39a489ecdb 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml @@ -73,16 +73,33 @@ require([ id = select.find('option').eq(index).attr('value'), item; - for(var i = 0, c = taxRateCollection.length; i < c; i++) { - if (taxRateCollection[i].tax_calculation_rate_id == id) { - item = taxRateCollection[i]; - break; - } - } - item.itemElement = that.prev(); - $('#tax-rate-form') - .dialogRates({itemRate: item}) - .dialogRates('open'); + $('body').trigger('processStart') + $.ajax({ + type: "POST", + data: {id:id}, + url: '<?php echo $block->getTaxRateLoadUrl()?>', + success: function(result, status) { + $('body').trigger('processStop'); + if (result.success) { + item=result.result; + item.itemElement = that.prev(); + $('#tax-rate-form') + .dialogRates({itemRate: item}) + .dialogRates('open'); + + } else { + if (result.error_message) + alert(result.error_message); + else + alert('<?php echo __('An error occurred'); ?>'); + } + }, + error: function () { + $('body').trigger('processStop'); + alert('<?php echo __('An error occurred'); ?>'); + }, + dataType: "json" + }); }; TaxRateEditableMultiselect.prototype.init = function () { @@ -142,6 +159,7 @@ require([ index = that.parent().index(), select = that.closest('.mselect-list').prev(); + $('body').trigger('processStart') var ajaxOptions = { type: 'POST', data: { @@ -151,12 +169,20 @@ require([ dataType: 'json', url: '<?php echo $block->getTaxRateDeleteUrl()?>', success: function(result, status) { + $('body').trigger('processStop'); if (result.success) { that.parent().remove(); select.find('option').eq(index).remove(); } else { - alert(result.error_message); + if (result.error_message) + alert(result.error_message); + else + alert('<?php echo __('An error occurred'); ?>'); } + }, + error: function () { + $('body').trigger('processStop'); + alert('<?php echo __('An error occurred'); ?>'); } }; $.ajax(ajaxOptions); @@ -215,13 +241,15 @@ require([ if (!taxRateFormElement.validation().valid()) { return; } - + $('.tax-rate-popup').trigger('processStart'); + $('.loading-mask').css('z-index','1004'); var ajaxOptions = { type: 'POST', data: itemRateData, dataType: 'json', url: '<?php echo $block->getTaxRateSaveUrl()?>', success: function(result, status) { + $('body').trigger('processStop'); if (result.success) { itemRate.code = result.code; if (itemRate.tax_calculation_rate_id) { @@ -238,10 +266,16 @@ require([ .val(itemRate.tax_calculation_rate_id); } taxRateForm.dialogRates("close"); - taxRateCollection.push(itemRate); } else { - alert(result.error_message); + if (result.error_message) + alert(result.error_message); + else + alert('<?php echo __('An error occurred'); ?>'); } + }, + error: function () { + $('body').trigger('processStop'); + alert('<?php echo __('An error occurred'); ?>'); } }; $.ajax(ajaxOptions); @@ -256,6 +290,7 @@ require([ } }] }); + $('.grid-loading-mask').hide(); } }; diff --git a/app/code/Magento/Tax/view/adminhtml/templates/rule/rate/form.phtml b/app/code/Magento/Tax/view/adminhtml/templates/rule/rate/form.phtml index eae01d9d0b302c71017afb3571349eb82bcc6043..d5c0d8aee3b6a8f84af22f3fd90f2c2afde1f0f5 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/rule/rate/form.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/rule/rate/form.phtml @@ -5,14 +5,13 @@ */ /* @var $block \Magento\Tax\Block\Adminhtml\Rate\Form */ ?> + +<div data-role="spinner" class="grid-loading-mask"> + <div class="grid-loader"></div> +</div> + <div class="form-inline" id="<?php echo $block->getNameInLayout() ?>" style="display:none"> <?php echo $block->getFormHtml();?> <?php echo $block->getChildHtml('form_after');?> </div> -<script> - - - var taxRateCollection = <?php echo json_encode($block->getRateCollection());?>; - -</script> diff --git a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportCsv.php b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportCsv.php index c49fc0c8e92594c5db3669c027bf282053fd4293..9f6f1cb8e6beeb2f860b824759c3a019cb1612eb 100644 --- a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportCsv.php +++ b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportCsv.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,6 +7,7 @@ namespace Magento\TaxImportExport\Controller\Adminhtml\Rate; use Magento\Framework\App\ResponseInterface; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Controller\ResultFactory; class ExportCsv extends \Magento\TaxImportExport\Controller\Adminhtml\Rate { @@ -18,8 +18,10 @@ class ExportCsv extends \Magento\TaxImportExport\Controller\Adminhtml\Rate */ public function execute() { - $this->_view->loadLayout(false); - $content = $this->_view->getLayout()->getChildBlock('adminhtml.tax.rate.grid', 'grid.export'); + /** @var \Magento\Framework\View\Result\Layout $resultLayout */ + $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT); + $content = $resultLayout->getLayout()->getChildBlock('adminhtml.tax.rate.grid', 'grid.export'); + return $this->fileFactory->create( 'rates.csv', $content->getCsvFile(), diff --git a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php index f698f7cbe655353dda0a808d032fa58f9f7e5b2a..1d5685802882b5ed3703222f7318511712493605 100644 --- a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php +++ b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -12,7 +11,7 @@ use Magento\Framework\App\Filesystem\DirectoryList; class ExportPost extends \Magento\TaxImportExport\Controller\Adminhtml\Rate { /** - * export action from import/export tax + * Export action from import/export tax * * @return ResponseInterface */ @@ -82,7 +81,6 @@ class ExportPost extends \Magento\TaxImportExport\Controller\Adminhtml\Rate $content .= $rate->toString($template) . "\n"; } - $this->_view->loadLayout(); return $this->fileFactory->create('tax_rates.csv', $content, DirectoryList::VAR_DIR); } } diff --git a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportXml.php b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportXml.php index 0ec4688e5d52e2bff1b45e3263fd3b14b8e5e3f5..38fc277576cc673254f8a0fc2dfe8d47439fa7a6 100644 --- a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportXml.php +++ b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportXml.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,6 +7,7 @@ namespace Magento\TaxImportExport\Controller\Adminhtml\Rate; use Magento\Framework\App\ResponseInterface; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Controller\ResultFactory; class ExportXml extends \Magento\TaxImportExport\Controller\Adminhtml\Rate { @@ -18,8 +18,10 @@ class ExportXml extends \Magento\TaxImportExport\Controller\Adminhtml\Rate */ public function execute() { - $this->_view->loadLayout(false); - $content = $this->_view->getLayout()->getChildBlock('adminhtml.tax.rate.grid', 'grid.export'); + /** @var \Magento\Framework\View\Result\Layout $resultLayout */ + $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT); + $content = $resultLayout->getLayout()->getChildBlock('adminhtml.tax.rate.grid', 'grid.export'); + return $this->fileFactory->create( 'rates.xml', $content->getExcelFile(), diff --git a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportExport.php b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportExport.php index ca34dd5197a7e941692bf263224bf094f08066ab..5ba0b3e87da0e7727e89aa3747d34916e2d0123a 100644 --- a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportExport.php +++ b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportExport.php @@ -1,30 +1,33 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\TaxImportExport\Controller\Adminhtml\Rate; +use Magento\Framework\Controller\ResultFactory; + class ImportExport extends \Magento\TaxImportExport\Controller\Adminhtml\Rate { /** * Import and export Page * - * @return void + * @return \Magento\Backend\Model\View\Result\Page */ public function execute() { - $this->_view->loadLayout(); - $this->_setActiveMenu( - 'Magento_TaxImportExport::system_convert_tax' - )->_addContent( - $this->_view->getLayout()->createBlock('Magento\TaxImportExport\Block\Adminhtml\Rate\ImportExportHeader') - )->_addContent( - $this->_view->getLayout()->createBlock('Magento\TaxImportExport\Block\Adminhtml\Rate\ImportExport') + /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + + $resultPage->setActiveMenu('Magento_TaxImportExport::system_convert_tax'); + $resultPage->addContent( + $resultPage->getLayout()->createBlock('Magento\TaxImportExport\Block\Adminhtml\Rate\ImportExportHeader') + ); + $resultPage->addContent( + $resultPage->getLayout()->createBlock('Magento\TaxImportExport\Block\Adminhtml\Rate\ImportExport') ); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); - $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Import and Export Tax Rates')); - $this->_view->renderLayout(); + $resultPage->getConfig()->getTitle()->prepend(__('Tax Zones and Rates')); + $resultPage->getConfig()->getTitle()->prepend(__('Import and Export Tax Rates')); + return $resultPage; } } diff --git a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportPost.php b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportPost.php index d072f6b82b28acb85e661f9b30776509601eaf92..663a0183b1e86cba8e888c9a9b194e24e99c9519 100644 --- a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportPost.php +++ b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ImportPost.php @@ -1,17 +1,18 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\TaxImportExport\Controller\Adminhtml\Rate; +use Magento\Framework\Controller\ResultFactory; + class ImportPost extends \Magento\TaxImportExport\Controller\Adminhtml\Rate { /** * import action from import/export tax * - * @return void + * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() { @@ -30,6 +31,9 @@ class ImportPost extends \Magento\TaxImportExport\Controller\Adminhtml\Rate } else { $this->messageManager->addError(__('Invalid file upload attempt')); } - $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl($this->getUrl('*'))); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setUrl($this->_redirect->getRedirectUrl()); + return $resultRedirect; } } diff --git a/app/code/Magento/TaxImportExport/composer.json b/app/code/Magento/TaxImportExport/composer.json index 334b8652a6d74ed73e037f5d001b62026444bac6..fd4d50bebb33888f1c8593d8772cca8af776b430 100644 --- a/app/code/Magento/TaxImportExport/composer.json +++ b/app/code/Magento/TaxImportExport/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-tax": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-tax": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Theme/Model/Config.php b/app/code/Magento/Theme/Model/Config.php index 5993e9bf010d5586384e03bdc4df50010f882547..39332cc9a0b7b7705db033cb7996e0fd3c482e90 100644 --- a/app/code/Magento/Theme/Model/Config.php +++ b/app/code/Magento/Theme/Model/Config.php @@ -9,6 +9,8 @@ */ namespace Magento\Theme\Model; +use Magento\Framework\App\Config\ScopeConfigInterface; + class Config { /** @@ -173,7 +175,7 @@ class Config protected function _assignThemeToDefaultScope($themeId, &$isReassigned) { $configPath = \Magento\Framework\View\DesignInterface::XML_PATH_THEME_ID; - $this->_configWriter->save($configPath, $themeId, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT); + $this->_configWriter->save($configPath, $themeId, ScopeConfigInterface::SCOPE_TYPE_DEFAULT); $isReassigned = true; return $this; } diff --git a/app/code/Magento/Theme/Model/View/Design.php b/app/code/Magento/Theme/Model/View/Design.php index f839d6ba900f71e2998634aa9e36776bcd863105..f0cf795f6b4482b9c8ac59bc444e62f4af24f14c 100644 --- a/app/code/Magento/Theme/Model/View/Design.php +++ b/app/code/Magento/Theme/Model/View/Design.php @@ -6,6 +6,8 @@ namespace Magento\Theme\Model\View; +use Magento\Framework\App\Config\ScopeConfigInterface; + /** * Keeps design settings for current request */ @@ -167,7 +169,7 @@ class Design implements \Magento\Framework\View\DesignInterface if ($this->_storeManager->isSingleStoreMode()) { $theme = $this->_scopeConfig->getValue( self::XML_PATH_THEME_ID, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ); } else { $theme = (string) $this->_scopeConfig->getValue( diff --git a/app/code/Magento/Theme/composer.json b/app/code/Magento/Theme/composer.json index cb64d49d6d2dae6c61f64b767b8fa2f2a895544f..fd23ba6ec42b957d3ff80683883ca990f4d9e14c 100644 --- a/app/code/Magento/Theme/composer.json +++ b/app/code/Magento/Theme/composer.json @@ -3,23 +3,23 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-widget": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/module-media-storage": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-require-js": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-widget": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/module-media-storage": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-require-js": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-translation": "0.74.0-beta6" + "magento/module-translation": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Theme/view/adminhtml/requirejs-config.js b/app/code/Magento/Theme/view/adminhtml/requirejs-config.js index 1c0d89ba473ef4811fe74cd4426863369b99dea8..0cc7098574c9d120f5235644bdf74ded7d9c82b2 100644 --- a/app/code/Magento/Theme/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/Theme/view/adminhtml/requirejs-config.js @@ -5,6 +5,9 @@ var config = { "shim": { + "extjs/ext-tree": [ + "prototype" + ], "extjs/ext-tree-checkbox": [ "extjs/ext-tree", "extjs/defaults" @@ -46,7 +49,8 @@ var config = { }, "deps": [ "js/theme", - "mage/backend/bootstrap" + "mage/backend/bootstrap", + "mage/adminhtml/globals" ], "paths": { "jquery/ui": "jquery/jquery-ui-1.9.2" diff --git a/app/code/Magento/Theme/view/base/requirejs-config.js b/app/code/Magento/Theme/view/base/requirejs-config.js index 637568a9c357ce6fe69cc80017903ec2e6e6e5a8..58dbd2b841a664e48e1cf98ba8d6bf73a5d40189 100644 --- a/app/code/Magento/Theme/view/base/requirejs-config.js +++ b/app/code/Magento/Theme/view/base/requirejs-config.js @@ -5,6 +5,11 @@ var config = { "waitSeconds": 0, + "map": { + "*": { + "mageUtils": "mage/utils/main" + } + }, "shim": { "jquery/jquery-migrate": ["jquery"], "jquery/jquery.hashchange": ["jquery", "jquery/jquery-migrate"], diff --git a/app/code/Magento/Translation/composer.json b/app/code/Magento/Translation/composer.json index 4b817066e92d7a9cccc5efbc1d2909409c383f0a..4a91a1055361628c26e0dd6c961f26925cc699c2 100644 --- a/app/code/Magento/Translation/composer.json +++ b/app/code/Magento/Translation/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta6", - "magento/module-developer": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-backend": "0.74.0-beta7", + "magento/module-developer": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php new file mode 100644 index 0000000000000000000000000000000000000000..152b025cfc003da954e17ad9688db719d213cb37 --- /dev/null +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -0,0 +1,261 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component; + +use Magento\Framework\Object; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\JsConfigInterface; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; + +/** + * Abstract class AbstractComponent + * @SuppressWarnings(PHPMD.NumberOfChildren) + */ +abstract class AbstractComponent extends Object implements UiComponentInterface, JsConfigInterface +{ + /** + * Render context + * + * @var ContextInterface + */ + protected $context; + + /** + * @var UiComponentInterface[] + */ + protected $components; + + /** + * @var array + */ + protected $componentData = []; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentInterface[] $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + array $components = [], + array $data = [] + ) { + $this->context = $context; + $this->components = $components; + parent::__construct($data); + } + + /** + * Get component context + * + * @return ContextInterface + */ + public function getContext() + { + return $this->context; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + // + } + + /** + * Produce and return block's html output + * + * @return string + */ + public function toHtml() + { + $this->render(); + } + + /** + * Render component + * + * @return string + */ + public function render() + { + $result = $this->getContext()->getRenderEngine()->render($this, $this->getTemplate()); + return $result; + } + + /** + * Get component name + * + * @return string + */ + public function getName() + { + return $this->getData('name'); + } + + /** + * Add component + * + * @param string $name + * @param UiComponentInterface $component + * @return void + */ + public function addComponent($name, UiComponentInterface $component) + { + $this->components[$name] = $component; + } + + /** + * @param string $name + * @return UiComponentInterface + */ + public function getComponent($name) + { + return isset($this->components[$name]) ? $this->components[$name] : null; + } + + /** + * Get components + * + * @return UiComponentInterface[] + */ + public function getChildComponents() + { + return $this->components; + } + + /** + * Get template + * + * @return string + */ + public function getTemplate() + { + return $this->getData('template') . '.xhtml'; + } + + /** + * Render child component + * + * @param string $name + * @return string + */ + public function renderChildComponent($name) + { + $result = null; + if (isset($this->components[$name])) { + $result = $this->components[$name]->render(); + } + return $result; + } + + /** + * Component data setter + * + * @param string|array $key + * @param mixed $value + * @return void + */ + public function setData($key, $value = null) + { + parent::setData($key, $value); + } + + /** + * Component data getter + * + * @param string $key + * @param string|int $index + * @return mixed + */ + public function getData($key = '', $index = null) + { + return parent::getData($key, $index); + } + + /** + * Set component configuration + * + * @return void + */ + protected function prepareConfiguration() + { + $config = $this->getDefaultConfiguration(); + if ($this->hasData('config')) { + $config = array_replace_recursive($config, $this->getData('config')); + } + + $this->setData('config', $config); + } + + /** + * Get default parameters + * + * @return array + */ + protected function getDefaultConfiguration() + { + return []; + } + + /** + * Get JS configuration + * + * @param UiComponentInterface $component + * @param null|string $extends + * @return array + */ + protected function getConfiguration(UiComponentInterface $component, $extends = null) + { + $jsConfig = (array) $component->getData('js_config'); + if (isset($jsConfig['extends'])) { + return $jsConfig; + } else if (null !== $extends) { + $jsConfig['extends'] = $extends; + } else { + $jsConfig['extends'] = $component->getContext()->getNamespace(); + } + + return $jsConfig; + } + + /** + * Get JS config + * + * @return array|string + */ + public function getJsConfig() + { + return (array) $this->getData('config'); + } + + /** + * @return array + */ + public function getDataSourceData() + { + $dataSources = []; + foreach ($this->getChildComponents() as $component) { + if ($component instanceof DataSourceInterface) { + $dataSources[] = [ + 'type' => $component->getComponentName(), + 'name' => $component->getName(), + 'dataScope' => $component->getContext()->getNamespace(), + 'config' => [ + 'data' => $component->getDataProvider()->getData() + ] + ]; + } + } + return $dataSources; + } +} diff --git a/app/code/Magento/Ui/Component/AbstractView.php b/app/code/Magento/Ui/Component/AbstractView.php deleted file mode 100644 index e67d0e1ff40ee6b3182c77bebb844c143fa8a84c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/AbstractView.php +++ /dev/null @@ -1,375 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -use Magento\Framework\View\Asset\Repository; -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\ConfigInterface; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; - -/** - * Abstract class AbstractView - * @SuppressWarnings(PHPMD.NumberOfChildren) - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -abstract class AbstractView extends Template implements UiComponentInterface -{ - /** - * Config builder - * - * @var ConfigBuilderInterface - */ - protected $configBuilder; - - /** - * View configuration data - * - * @var ConfigInterface - */ - protected $config; - - /** - * Render context - * - * @var Context - */ - protected $renderContext; - - /** - * Config factory - * - * @var ConfigFactory - */ - protected $configFactory; - - /** - * Content type factory - * - * @var ContentTypeFactory - */ - protected $contentTypeFactory; - - /** - * Asset service - * - * @var Repository - */ - protected $assetRepo; - - /** - * Data provider factory - * - * @var DataProviderFactory - */ - protected $dataProviderFactory; - - /** - * @var \Magento\Ui\DataProvider\Manager - */ - protected $dataManager; - - /** - * Elements for the render - * - * @var ElementRendererInterface[] - */ - protected $elements = []; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param array $data - */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - array $data = [] - ) { - $this->renderContext = $renderContext; - $this->contentTypeFactory = $contentTypeFactory; - $this->assetRepo = $context->getAssetRepository(); - $this->configFactory = $configFactory; - $this->configBuilder = $configBuilder; - $this->dataProviderFactory = $dataProviderFactory; - $this->dataManager = $dataProviderManager; - parent::__construct($context, $data); - } - - /** - * Update data - * - * @param array $data - * @return void - */ - public function update(array $data = []) - { - if (!empty($data)) { - $this->_data = array_merge_recursive($this->_data, $data); - } - } - - /** - * Prepare component data - * - * @return void - */ - public function prepare() - { - // - } - - /** - * Render content - * - * @param array $data - * @return string - */ - public function render(array $data = []) - { - $prevData = $this->getData(); - $this->update($data); - - $renderResult = $this->contentTypeFactory->get($this->renderContext->getAcceptType()) - ->render($this, $this->getContentTemplate()); - - $this->setData($prevData); - - return $renderResult; - } - - /** - * Render label - * - * @return mixed|string - */ - public function renderLabel() - { - return $this->contentTypeFactory->get($this->renderContext->getAcceptType()) - ->render($this, $this->getLabelTemplate()); - } - - /** - * Render element - * - * @param string $elementName - * @param array $arguments - * @return mixed|string - */ - public function renderElement($elementName, array $arguments) - { - $element = $this->renderContext->getRender()->getUiElementView($elementName); - $result = $element->render($arguments); - return $result; - } - - /** - * Render component label - * - * @param string $elementName - * @param array $arguments - * @return string - */ - public function renderElementLabel($elementName, array $arguments) - { - $element = $this->renderContext->getRender()->getUiElementView($elementName); - $prevData = $element->getData(); - $element->update($arguments); - $result = $element->renderLabel(); - $element->setData($prevData); - return $result; - } - - /** - * Shortcut for rendering as HTML - * (used for backward compatibility with standard rendering mechanism via layout interface) - * - * @return string - */ - public function toHtml() - { - return $this->render(); - } - - /** - * Getting label template - * - * @return string|false - */ - public function getLabelTemplate() - { - return 'Magento_Ui::label/default.phtml'; - } - - /** - * Getting content template - * - * @return string|false - */ - public function getContentTemplate() - { - return $this->getData('content_template'); - } - - /** - * Get Layout Node - * - * @param string $fullName - * @param mixed $default - * @return array - */ - public function getLayoutElement($fullName, $default = null) - { - return $this->renderContext->getStorage()->getLayoutNode($fullName, $default); - } - - /** - * Get name component instance - * - * @return string - */ - public function getName() - { - return $this->config->getName(); - } - - /** - * Get parent name component instance - * - * @return string - */ - public function getParentName() - { - return $this->config->getParentName(); - } - - /** - * Get configuration builder - * - * @return ConfigBuilderInterface - */ - public function getConfigBuilder() - { - return $this->configBuilder; - } - - /** - * Set component configuration - * - * @param null $configData - * @param null $name - * @param null $parentName - * @return void - */ - public function prepareConfiguration($configData = null, $name = null, $parentName = null) - { - $arguments = []; - $arguments['name'] = $name ?: $this->renderContext->getNamespace() . '_' . $this->getNameInLayout(); - $arguments['parentName'] = $parentName ?: $this->renderContext->getNamespace(); - if ($configData) { - $arguments['configuration'] = $configData; - } - $this->config = $this->configFactory->create($arguments); - $this->renderContext->getStorage()->addComponentsData($this->config); - } - - /** - * Get component configuration - * - * @return ConfigInterface - */ - public function getConfig() - { - return $this->config; - } - - /** - * Get render context - * - * @return Context - */ - public function getRenderContext() - { - return $this->renderContext; - } - - /** - * Get elements to the render - * - * @return ElementRendererInterface[] - */ - public function getElements() - { - return $this->elements; - } - - /** - * Set elements for the render - * - * @param ElementRendererInterface[] $elements - * @return mixed|void - */ - public function setElements(array $elements) - { - $this->elements = $elements; - } - - /** - * Get default parameters - * - * @return array - */ - protected function getDefaultConfiguration() - { - return []; - } - - /** - * Get render engine - * - * @return \Magento\Ui\ContentType\ContentTypeInterface - */ - protected function getRenderEngine() - { - return $this->contentTypeFactory->get($this->renderContext->getAcceptType()); - } - - /** - * Create data provider - * - * @return void - */ - protected function createDataProviders() - { - if ($this->hasData('data_provider_pool')) { - foreach ($this->getData('data_provider_pool') as $name => $config) { - $arguments = empty($config['arguments']) ? [] : $config['arguments']; - $arguments['params'] = $this->renderContext->getRequestParams(); - - $dataProvider = $this->dataProviderFactory->create($config['class'], $arguments); - $this->renderContext->getStorage()->addDataProvider($name, $dataProvider); - } - } - } -} diff --git a/app/code/Magento/Ui/Component/Container.php b/app/code/Magento/Ui/Component/Container.php new file mode 100644 index 0000000000000000000000000000000000000000..84e86a9fd58cafb876e9b41fbf46dc6405896fee --- /dev/null +++ b/app/code/Magento/Ui/Component/Container.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component; + +/** + * Class Container + */ +class Container extends AbstractComponent +{ + const NAME = 'container'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + $type = $this->getData('type'); + return static::NAME . (!empty($type) ? '.' . $type : ''); + } + + /** + * Register component + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } +} diff --git a/app/code/Magento/Ui/Component/Container/Content.php b/app/code/Magento/Ui/Component/Container/Content.php deleted file mode 100644 index 94c43012e2eac05b4bfae9422461a0be23d1017a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Container/Content.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Container; - -use Magento\Ui\Component\AbstractView; - -/** - * Class Content - */ -class Content extends AbstractView -{ - /** - * Prepare component data - * - * @return $this|void - */ - public function prepare() - { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - - $this->prepareConfiguration($configData); - } -} diff --git a/app/code/Magento/Ui/Component/Control/Action.php b/app/code/Magento/Ui/Component/Control/Action.php index 5021b8f7c481789233e9135655101b9e08a597e8..8f19a3b84e739d254e66da779aa1443701d66a60 100644 --- a/app/code/Magento/Ui/Component/Control/Action.php +++ b/app/code/Magento/Ui/Component/Control/Action.php @@ -5,11 +5,23 @@ */ namespace Magento\Ui\Component\Control; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponent\Control\ControlInterface; /** * Class Action */ -class Action extends AbstractView implements ControlInterface +class Action extends AbstractComponent implements ControlInterface { + const NAME = 'action'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Control/ActionPool.php b/app/code/Magento/Ui/Component/Control/ActionPool.php index 97f5afdba9ed14cf1135cbd2f3e95caa436c764a..74f327fec1531089563d850815d93ad1bdbfc351 100644 --- a/app/code/Magento/Ui/Component/Control/ActionPool.php +++ b/app/code/Magento/Ui/Component/Control/ActionPool.php @@ -5,8 +5,11 @@ */ namespace Magento\Ui\Component\Control; +use Magento\Framework\View\Element\AbstractBlock; +use Magento\Framework\View\Element\BlockInterface; use Magento\Framework\View\Element\UiComponent\Context; use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\Control\ActionPoolInterface; /** * Class ActionPool @@ -40,7 +43,7 @@ class ActionPool implements ActionPoolInterface protected $itemFactory; /** - * @var \Magento\Framework\View\Element\AbstractBlock + * @var AbstractBlock */ protected $toolbarBlock; @@ -54,8 +57,18 @@ class ActionPool implements ActionPoolInterface { $this->context = $context; $this->itemFactory = $itemFactory; - $this->toolbarBlock = $this->context->getPageLayout() - ? $this->context->getPageLayout()->getBlock(static::ACTIONS_PAGE_TOOLBAR) : false; + } + + /** + * Get toolbar block + * + * @return bool|BlockInterface + */ + public function getToolbar() + { + return $this->context->getPageLayout() + ? $this->context->getPageLayout()->getBlock(static::ACTIONS_PAGE_TOOLBAR) + : false; } /** @@ -63,18 +76,19 @@ class ActionPool implements ActionPoolInterface * * @param string $key * @param array $data - * @param UiComponentInterface $view + * @param UiComponentInterface $component * @return void */ - public function add($key, array $data, UiComponentInterface $view) + public function add($key, array $data, UiComponentInterface $component) { $data['id'] = isset($data['id']) ? $data['id'] : $key; - if ($this->toolbarBlock !== false) { + $toolbar = $this->getToolbar(); + if ($toolbar !== false) { $this->items[$key] = $this->itemFactory->create(); $this->items[$key]->setData($data); - $container = $this->createContainer($key, $view); - $this->toolbarBlock->setChild($key, $container); + $container = $this->createContainer($key, $component); + $toolbar->setChild($key, $container); } } @@ -108,7 +122,7 @@ class ActionPool implements ActionPoolInterface * * @param string $key * @param UiComponentInterface $view - * @return \Magento\Ui\Component\Control\Container + * @return Container */ protected function createContainer($key, UiComponentInterface $view) { @@ -122,6 +136,7 @@ class ActionPool implements ActionPoolInterface ] ] ); + return $container; } } diff --git a/app/code/Magento/Ui/Component/Control/Button.php b/app/code/Magento/Ui/Component/Control/Button.php index 51c839b14b2a8dc0592503a6df0619205e682e61..404bbf04bd4484287cdaa4dc63291242792b93ad 100644 --- a/app/code/Magento/Ui/Component/Control/Button.php +++ b/app/code/Magento/Ui/Component/Control/Button.php @@ -6,11 +6,12 @@ namespace Magento\Ui\Component\Control; use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\UiComponent\Control\ControlInterface; /** * Class Button */ -class Button extends Template +class Button extends Template implements ControlInterface { /** * Define block template @@ -72,7 +73,7 @@ class Button extends Template } else { $url = $this->hasData('url') ? $this->getData('url') : $this->getUrl(); if (!empty($url)) { - return sprintf("setLocation('%s');", $url); + return sprintf("location.href = '%s';", $url); } return null; diff --git a/app/code/Magento/Ui/Component/Control/Container.php b/app/code/Magento/Ui/Component/Control/Container.php index b4da5f6740eeddc3cc4a7c54b0c17c30eccf709f..2873e2618a168279d231b701a7007afec8de96ca 100644 --- a/app/code/Magento/Ui/Component/Control/Container.php +++ b/app/code/Magento/Ui/Component/Control/Container.php @@ -6,6 +6,7 @@ namespace Magento\Ui\Component\Control; use Magento\Framework\View\Element\AbstractBlock; +use Magento\Framework\View\Element\UiComponent\Control\ControlInterface; /** * Class Container @@ -15,19 +16,19 @@ class Container extends AbstractBlock /** * Default button class */ - const DEFAULT_BUTTON = 'Magento\Ui\Component\Control\Button'; + const DEFAULT_CONTROL = 'Magento\Ui\Component\Control\Button'; /** * Create button renderer * * @param string $blockName * @param string $blockClassName - * @return \Magento\Ui\Component\Control\Button + * @return ControlInterface */ protected function createButton($blockName, $blockClassName = null) { if (null === $blockClassName) { - $blockClassName = static::DEFAULT_BUTTON; + $blockClassName = static::DEFAULT_CONTROL; } return $this->getLayout()->createBlock($blockClassName, $blockName); @@ -40,7 +41,7 @@ class Container extends AbstractBlock */ protected function _toHtml() { - /** @var \Magento\Ui\Component\Control\Item $item */ + /** @var Item $item */ $item = $this->getButtonItem(); $data = $item->getData(); diff --git a/app/code/Magento/Ui/Component/Control/ControlInterface.php b/app/code/Magento/Ui/Component/Control/ControlInterface.php deleted file mode 100644 index 6949ff096573b1045cccae62f42fd9e37e78e42a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Control/ControlInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Control; - -use Magento\Framework\View\Element\UiComponentInterface; - -/** - * Interface ControlInterface - */ -interface ControlInterface extends UiComponentInterface -{ - // -} diff --git a/app/code/Magento/Ui/Component/Control/Link.php b/app/code/Magento/Ui/Component/Control/Link.php index cdc3c166322a00249d6abd9f4d368246460e164b..ce99dc5064789af0ae33309505f9d9a4c469458f 100644 --- a/app/code/Magento/Ui/Component/Control/Link.php +++ b/app/code/Magento/Ui/Component/Control/Link.php @@ -5,12 +5,23 @@ */ namespace Magento\Ui\Component\Control; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponent\Control\ControlInterface; /** * Class Link */ -class Link extends AbstractView implements ControlInterface +class Link extends AbstractComponent implements ControlInterface { - // + const NAME = 'link'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/DataSource.php b/app/code/Magento/Ui/Component/DataSource.php new file mode 100644 index 0000000000000000000000000000000000000000..5f50643d73628e55cf5879094b277b1ee019f8b6 --- /dev/null +++ b/app/code/Magento/Ui/Component/DataSource.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component; + +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; + +/** + * Class DataSource + */ +class DataSource extends AbstractComponent implements DataSourceInterface +{ + const NAME = 'dataSource'; + + /** + * @var DataProviderInterface + */ + protected $dataProvider; + + /** + * Constructor + * + * @param ContextInterface $context + * @param DataProviderInterface $dataProvider + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + DataProviderInterface $dataProvider, + array $components = [], + array $data = [] + ) { + $this->dataProvider = $dataProvider; + $context->setDataProvider($dataProvider); + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $config = $this->getData('config'); + if (isset($config['update_url'])) { + $config['update_url'] = $this->getContext()->getUrl($config['update_url']); + $this->setData('config', $config); + } + + $jsConfig = $this->getConfiguration($this); + unset($jsConfig['extends']); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * @return DataProviderInterface + */ + public function getDataProvider() + { + return $this->dataProvider; + } +} diff --git a/app/code/Magento/Ui/Component/ElementRenderer.php b/app/code/Magento/Ui/Component/ElementRenderer.php deleted file mode 100644 index 3d3e2857aa61b447c97b82a24c209e79afa9c7a3..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/ElementRenderer.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -use Magento\Framework\View\Element\UiComponentInterface; - -/** - * Class ElementRenderer - */ -class ElementRenderer implements ElementRendererInterface -{ - /** - * Ui component - * - * @var UiComponentInterface - */ - protected $element; - - /** - * Data to render - * - * @var array - */ - protected $data; - - /** - * Constructor - * - * @param UiComponentInterface $element - * @param array $data - */ - public function __construct(UiComponentInterface $element, array $data) - { - $this->element = $element; - $this->data = $data; - } - - /** - * Render element - * - * @return string - */ - public function render() - { - return $this->element->render($this->data); - } -} diff --git a/app/code/Magento/Ui/Component/ElementRendererBuilder.php b/app/code/Magento/Ui/Component/ElementRendererBuilder.php deleted file mode 100644 index 4672866fc6299fa081258443d9bc149a4e2a733e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/ElementRendererBuilder.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\View\Element\UiComponentInterface; - -/** - * Class ElementRendererBuilder - */ -class ElementRendererBuilder -{ - /** - * Object manager - * - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * Instance class name - * - * @var string - */ - protected $instanceClass = 'Magento\Ui\Component\ElementRenderer'; - - /** - * Constructor - * - * @param ObjectManagerInterface $objectManager - */ - public function __construct(ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * Create element to the render - * - * @param UiComponentInterface $element - * @param array $renderData - * @return ElementRendererInterface - */ - public function create(UiComponentInterface $element, array $renderData) - { - return $this->objectManager->create($this->instanceClass, ['element' => $element, 'data' => $renderData]); - } -} diff --git a/app/code/Magento/Ui/Component/ElementRendererInterface.php b/app/code/Magento/Ui/Component/ElementRendererInterface.php deleted file mode 100644 index 2cffde7c864654a4d2618b43af648084eed71127..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/ElementRendererInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -/** - * Interface ElementRendererInterface - */ -interface ElementRendererInterface -{ - /** - * Render element - * - * @return string - */ - public function render(); -} diff --git a/app/code/Magento/Ui/Component/Filter/FilterAbstract.php b/app/code/Magento/Ui/Component/Filter/FilterAbstract.php deleted file mode 100644 index 0da2dc77f3ea2631b28e9bd16e958e9f426af660..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/FilterAbstract.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter; - -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\AbstractView; -use Magento\Ui\Component\Filter\FilterPool as FilterPoolProvider; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; - -/** - * Class Filter - */ -abstract class FilterAbstract extends AbstractView implements FilterInterface -{ - /** - * Filter variable name - */ - const FILTER_VAR = 'filter'; - - /** - * Filters pool - * - * @var FilterPoolProvider - */ - protected $filterPool; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param FilterPoolProvider $filterPool - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param array $data - */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - FilterPoolProvider $filterPool, - array $data = [] - ) { - $this->filterPool = $filterPool; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); - } - - /** - * Prepare component data - * - * @return void - */ - public function prepare() - { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - - $this->prepareConfiguration($configData); - } - - /** - * Get condition by data type - * - * @param string|array $value - * @return array|null - */ - public function getCondition($value) - { - return $value; - } -} diff --git a/app/code/Magento/Ui/Component/Filter/FilterInterface.php b/app/code/Magento/Ui/Component/Filter/FilterInterface.php deleted file mode 100644 index aa1ccfe73e37b2568da3ea5e841be2aec6a89afe..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/FilterInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter; - - -/** - * Interface FilterInterface - */ -interface FilterInterface -{ - /** - * Get condition by data type - * - * @param string|array $value - * @return array|null - */ - public function getCondition($value); -} diff --git a/app/code/Magento/Ui/Component/Filter/FilterPool.php b/app/code/Magento/Ui/Component/Filter/FilterPool.php deleted file mode 100644 index 40d15a2c69d524a874fa9703df4db6e27c8dae20..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/FilterPool.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter; - -use Magento\Framework\ObjectManagerInterface; - -/** - * Class FilterPool - */ -class FilterPool -{ - /** - * Filter types - * - * @var array - */ - protected $filterTypes = []; - - /** - * Filters poll - * - * @var FilterInterface[] - */ - protected $filters = []; - - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * Constructor - * - * @param ObjectManagerInterface $objectManager - * @param array $filters - */ - public function __construct(ObjectManagerInterface $objectManager, array $filters = []) - { - $this->objectManager = $objectManager; - $this->filterTypes = $filters; - } - - /** - * Get filter by type - * - * @param string $filterName - * @return FilterInterface - * @throws \InvalidArgumentException - */ - public function getFilter($filterName) - { - if (!isset($this->filters[$filterName])) { - if (!isset($this->filterTypes[$filterName])) { - throw new \InvalidArgumentException(sprintf('Unknown filter type "%s"', $filterName)); - } - $this->filters[$filterName] = $this->objectManager->create($this->filterTypes[$filterName]); - } - - return $this->filters[$filterName]; - } -} diff --git a/app/code/Magento/Ui/Component/Filter/Type/Date.php b/app/code/Magento/Ui/Component/Filter/Type/Date.php deleted file mode 100644 index 90b7e16a4aeeb16e7d70fa2a4da2663a0f4df92e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/Type/Date.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter\Type; - -use Magento\Framework\Locale\ResolverInterface; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\Filter\FilterAbstract; -use Magento\Ui\Component\Filter\FilterPool; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; - -/** - * Class Date - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class Date extends FilterAbstract -{ - /** - * Timezone library - * - * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface - */ - protected $localeDate; - - /** - * Scope config - * - * @var \Magento\Framework\App\Config\ScopeConfigInterface - */ - protected $scopeConfig; - - /** - * Locale resolver - * - * @var \Magento\Framework\Locale\ResolverInterface - */ - protected $localeResolver; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param FilterPool $filterPool - * @param ResolverInterface $localeResolver - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - FilterPool $filterPool, - ResolverInterface $localeResolver, - array $data = [] - ) { - $this->localeDate = $context->getLocaleDate(); - $this->scopeConfig = $context->getScopeConfig(); - $this->localeResolver = $localeResolver; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $filterPool, - $data - ); - } - - /** - * Get condition by data type - * - * @param string|array $value - * @return array|null - */ - public function getCondition($value) - { - return $this->convertValue($value); - } - - /** - * Convert value - * - * @param array|string $value - * @return array|null - */ - protected function convertValue($value) - { - if (!empty($value['from']) || !empty($value['to'])) { - $locale = $this->localeResolver->getLocale(); - if (!empty($value['from'])) { - $value['orig_from'] = $value['from']; - $value['from'] = $this->convertDate(strtotime($value['from']), $locale); - } - if (!empty($value['to'])) { - $value['orig_to'] = $value['to']; - $value['to'] = $this->convertDate(strtotime($value['to']), $locale); - } - $value['datetime'] = true; - $value['locale'] = $this->localeResolver->getLocale(); - } else { - $value = null; - } - - return $value; - } - - /** - * Convert given date to default (UTC) timezone - * - * @param int $date - * @param string $locale - * @return \DateTime|null - */ - protected function convertDate($date, $locale) - { - try { - $dateObj = $this->localeDate->date(new \DateTime($date), $locale, false); - $dateObj->setTime(0, 0, 0); - //convert store date to default date in UTC timezone without DST - $dateObj->setTimezone(new \DateTimeZone('UTC')); - return $dateObj; - } catch (\Exception $e) { - return null; - } - } -} diff --git a/app/code/Magento/Ui/Component/Filter/Type/Input.php b/app/code/Magento/Ui/Component/Filter/Type/Input.php deleted file mode 100644 index 214ae8e8a671c980590352b14943a426887b9799..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/Type/Input.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter\Type; - -use Magento\Ui\Component\Filter\FilterAbstract; - -/** - * Class Input - */ -class Input extends FilterAbstract -{ - /** - * Get condition by data type - * - * @param string|array $value - * @return array|null - */ - public function getCondition($value) - { - $condition = null; - if (!empty($value) || is_numeric($value)) { - $condition = ['like' => sprintf('%%%s%%', $value)]; - } - - return $condition; - } -} diff --git a/app/code/Magento/Ui/Component/Filter/Type/Range.php b/app/code/Magento/Ui/Component/Filter/Type/Range.php deleted file mode 100644 index 25583f994f40007f45e654575471e2b9889a4641..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/Type/Range.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter\Type; - -use Magento\Ui\Component\Filter\FilterAbstract; - -/** - * Class Range - */ -class Range extends FilterAbstract -{ - /** - * Get condition by data type - * - * @param array|string $value - * @return array|null - */ - public function getCondition($value) - { - if (!empty($value['from']) || !empty($value['to'])) { - if (isset($value['from']) && empty($value['from']) && $value['from'] !== '0') { - $value['orig_from'] = $value['from']; - $value['from'] = null; - } - if (isset($value['to']) && empty($value['to']) && $value['to'] !== '0') { - $value['orig_to'] = $value['to']; - $value['to'] = null; - } - } else { - $value = null; - } - - return $value; - } -} diff --git a/app/code/Magento/Ui/Component/Filter/Type/Select.php b/app/code/Magento/Ui/Component/Filter/Type/Select.php deleted file mode 100644 index 309049fef60012b1f86d7094f8b3211ee378e84b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/Type/Select.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter\Type; - -use Magento\Ui\Component\Filter\FilterAbstract; - -/** - * Class Select - */ -class Select extends FilterAbstract -{ - /** - * Get condition by data type - * - * @param string|array $value - * @return array|null - */ - public function getCondition($value) - { - $condition = null; - if (!empty($value) || is_numeric($value)) { - $condition = ['eq' => $value]; - } - - return $condition; - } -} diff --git a/app/code/Magento/Ui/Component/Filter/Type/Store.php b/app/code/Magento/Ui/Component/Filter/Type/Store.php deleted file mode 100644 index aa0495336a281bb632eeffea466e9758665559ee..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Filter/Type/Store.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Filter\Type; - -use Magento\Ui\Component\Filter\FilterAbstract; - -/** - * Class Store - */ -class Store extends FilterAbstract -{ -} diff --git a/app/code/Magento/Ui/Component/FilterPool.php b/app/code/Magento/Ui/Component/FilterPool.php deleted file mode 100644 index fae9e248d58ab64d3efd2c5355a4dd4b6517524d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/FilterPool.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\Filter\FilterAbstract; -use Magento\Ui\Component\Filter\FilterPool as FilterPoolProvider; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; - -/** - * Class FilterPool - */ -class FilterPool extends AbstractView -{ - /** - * Filters pool - * - * @var FilterPoolProvider - */ - protected $filterPoolProvider; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param FilterPoolProvider $filterPoolProvider - * @param array $data - */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - FilterPoolProvider $filterPoolProvider, - array $data = [] - ) { - $this->filterPoolProvider = $filterPoolProvider; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); - } - - /** - * Prepare component data - * - * @return void - */ - public function prepare() - { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - $this->prepareConfiguration($configData); - $this->updateDataCollection(); - } - - /** - * Get fields - * - * @return array - */ - public function getFields() - { - $meta = $this->renderContext->getStorage()->getMeta($this->getParentName()); - $fields = []; - if (isset($meta['fields'])) { - foreach ($meta['fields'] as $name => $config) { - if (isset($config['filterable']) && $config['filterable'] === false) { - continue; - } - $fields[$name] = $config; - } - } - return $fields; - } - - /** - * Get active filters - * - * @return array - */ - public function getActiveFilters() - { - $metaData = $this->renderContext->getStorage()->getMeta($this->getParentName()); - $metaData = $metaData['fields']; - $filters = []; - $filterData = $this->prepareFilterString( - $this->renderContext->getRequestParam(FilterAbstract::FILTER_VAR) - ); - foreach ($filterData as $field => $value) { - if (isset($metaData[$field]['filter_type'])) { - $filters[$field] = [ - 'label' => $metaData[$field]['label'], - 'current_display_value' => $value, - ]; - } - } - - return $filters; - } - - /** - * Update data collection - * - * @return void - */ - protected function updateDataCollection() - { - $collection = $this->renderContext->getStorage()->getDataCollection($this->getParentName()); - - $metaData = $this->renderContext->getStorage()->getMeta($this->getParentName()); - $metaData = $metaData['fields']; - $filterData = $this->prepareFilterString( - $this->renderContext->getRequestParam(FilterAbstract::FILTER_VAR) - ); - foreach ($filterData as $field => $value) { - if (!isset($metaData[$field]['filter_type'])) { - continue; - } - $condition = $this->filterPoolProvider->getFilter($metaData[$field]['filter_type'])->getCondition($value); - if ($condition !== null) { - $collection->addFieldToFilter($field, $condition); - } - } - } - - /** - * Get list of required filters - * - * @return array - */ - protected function getListOfRequiredFilters() - { - $result = []; - foreach ($this->getFields() as $field) { - $result[] = isset($field['filter_type']) ? $field['filter_type'] : $field['input_type']; - } - - return $result; - } - - /** - * Decode filter string - * - * @param string $filterString - * @return array - */ - protected function prepareFilterString($filterString) - { - $data = []; - $filterString = base64_decode($filterString); - parse_str($filterString, $data); - array_walk_recursive( - $data, - // @codingStandardsIgnoreStart - /** - * Decodes URL-encoded string and trims whitespaces from the beginning and end of a string - * - * @param string $value - */ - // @codingStandardsIgnoreEnd - function (&$value) { - $value = trim(rawurldecode($value)); - } - ); - return $data; - } -} diff --git a/app/code/Magento/Ui/Component/Filters.php b/app/code/Magento/Ui/Component/Filters.php new file mode 100644 index 0000000000000000000000000000000000000000..75c5b0d0472b947d132c779d3b079be5fd5d4af1 --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component; + +/** + * Class Filters + */ +class Filters extends AbstractComponent +{ + const NAME = 'filters'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Register component. + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } +} diff --git a/app/code/Magento/Ui/Component/Filters/Type/AbstractFilter.php b/app/code/Magento/Ui/Component/Filters/Type/AbstractFilter.php new file mode 100644 index 0000000000000000000000000000000000000000..d2aa51c314a4b5f0979ba80093959a3364382350 --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters/Type/AbstractFilter.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Filters\Type; + +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + +/** + * Abstract class AbstractFilter + */ +abstract class AbstractFilter extends AbstractComponent +{ + /** + * Filter variable name + */ + const FILTER_VAR = 'filters'; + + /** + * Filter data + * + * @var array + */ + protected $filterData; + + /** + * @var UiComponentFactory + */ + protected $uiComponentFactory; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + array $components = [], + array $data = [] + ) { + $this->uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + + $this->filterData = $this->getContext()->getRequestParam(static::FILTER_VAR); + } +} diff --git a/app/code/Magento/Ui/Component/Filters/Type/Date.php b/app/code/Magento/Ui/Component/Filters/Type/Date.php new file mode 100644 index 0000000000000000000000000000000000000000..4211b51838b8eaf3736ab38cd3b612b7486ca5aa --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters/Type/Date.php @@ -0,0 +1,121 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Filters\Type; + +use Magento\Ui\Component\Form\Element\DataType\Date as DataTypeDate; + +/** + * Class Date + */ +class Date extends AbstractFilter +{ + const NAME = 'filter_date'; + + const COMPONENT = 'date'; + + /** + * Wrapped component + * + * @var DataTypeDate + */ + protected $wrappedComponent; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + static::COMPONENT, + ['context' => $this->getContext()] + ); + $this->wrappedComponent->prepare(); + + $this->applyFilter(); + $jsConfig = array_replace_recursive( + $this->getConfiguration($this->wrappedComponent), + $this->getConfiguration($this) + ); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Get JS config + * + * @return array + */ + public function getJsConfig() + { + return array_replace_recursive( + (array) $this->wrappedComponent->getData('config'), + (array) $this->getData('config') + ); + } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } + + /** + * Get condition + * + * @return array|null + */ + protected function getCondition() + { + $value = isset($this->filterData[$this->getName()]) ? $this->filterData[$this->getName()] : null; + if (!empty($value['from']) || !empty($value['to'])) { + if (!empty($value['from'])) { + $value['orig_from'] = $value['from']; + $value['from'] = $this->wrappedComponent->convertDate( + $value['from'], + $this->wrappedComponent->getLocale() + ); + } else { + unset($value['from']); + } + if (!empty($value['to'])) { + $value['orig_to'] = $value['to']; + $value['to'] = $this->wrappedComponent->convertDate( + $value['to'], + $this->wrappedComponent->getLocale() + ); + } else { + unset($value['to']); + } + $value['datetime'] = true; + $value['locale'] = $this->wrappedComponent->getLocale(); + } else { + $value = null; + } + + return $value; + } +} diff --git a/app/code/Magento/Ui/Component/Filters/Type/DateRange.php b/app/code/Magento/Ui/Component/Filters/Type/DateRange.php new file mode 100644 index 0000000000000000000000000000000000000000..daae0ab2ca7327188259f6c9d9035997dfce5022 --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters/Type/DateRange.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Filters\Type; + +use Magento\Ui\Component\Form\Element\DataType\Date as DataTypeDate; + +/** + * Class DateRange + */ +class DateRange extends AbstractFilter +{ + const NAME = 'filter_range'; + + const COMPONENT = 'date'; + + /** + * Wrapped component + * + * @var DataTypeDate + */ + protected $wrappedComponent; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + static::COMPONENT, + ['context' => $this->getContext()] + ); + $this->wrappedComponent->prepare(); + + $this->applyFilter(); + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } + + /** + * Get condition by data type + * + * @return array|null + */ + public function getCondition() + { + $value = isset($this->filterData[$this->getName()]) ? $this->filterData[$this->getName()] : null; + if (!empty($value['from']) || !empty($value['to'])) { + if (!empty($value['from'])) { + $value['orig_from'] = $value['from']; + $value['from'] = $this->wrappedComponent->convertDate( + $value['from'], + $this->wrappedComponent->getLocale() + ); + } else { + unset($value['from']); + } + if (!empty($value['to'])) { + $value['orig_to'] = $value['to']; + $value['to'] = $this->wrappedComponent->convertDate( + $value['to'], + $this->wrappedComponent->getLocale() + ); + } else { + unset($value['to']); + } + $value['datetime'] = true; + $value['locale'] = $this->wrappedComponent->getLocale(); + } else { + $value = null; + } + + return $value; + } +} diff --git a/app/code/Magento/Ui/Component/Filters/Type/Input.php b/app/code/Magento/Ui/Component/Filters/Type/Input.php new file mode 100644 index 0000000000000000000000000000000000000000..5a9e68b0bd72540dc22c9644094bc81c575631b8 --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters/Type/Input.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Filters\Type; + +use Magento\Ui\Component\Form\Element\Input as ElementInput; + +/** + * Class Input + */ +class Input extends AbstractFilter +{ + const NAME = 'filter_input'; + + const COMPONENT = 'input'; + + /** + * Wrapped component + * + * @var ElementInput + */ + protected $wrappedComponent; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + static::COMPONENT, + ['context' => $this->getContext()] + ); + $this->wrappedComponent->prepare(); + + $this->applyFilter(); + $jsConfig = array_replace_recursive( + $this->getConfiguration($this->wrappedComponent), + $this->getConfiguration($this) + ); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } + + /** + * Get condition by data type + * + * @return array|null + */ + public function getCondition() + { + $value = isset($this->filterData[$this->getName()]) ? $this->filterData[$this->getName()] : null; + $condition = null; + if (!empty($value) || is_numeric($value)) { + $condition = ['like' => sprintf('%%%s%%', $value)]; + } + + return $condition; + } +} diff --git a/app/code/Magento/Ui/Component/Filters/Type/Range.php b/app/code/Magento/Ui/Component/Filters/Type/Range.php new file mode 100644 index 0000000000000000000000000000000000000000..7892ef98f52222d4c75d32ef4676f09656f4e827 --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters/Type/Range.php @@ -0,0 +1,100 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Filters\Type; + +/** + * Class Range + */ +class Range extends AbstractFilter +{ + const NAME = 'filter_range'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $this->applyFilter(); + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } + + /** + * Get condition by data type + * + * @return array|null + */ + public function getCondition() + { + $value = isset($this->filterData[$this->getName()]) ? $this->filterData[$this->getName()] : null; + if (!empty($value['from']) || !empty($value['to'])) { + $value = $this->prepareFrom($value); + $value = $this->prepareTo($value); + } else { + $value = null; + } + + return $value; + } + + /** + * Prepare "from" value + * + * @param array $value + * @return array + */ + protected function prepareFrom(array $value) + { + if (isset($value['from']) && empty($value['from']) && $value['from'] !== '0') { + $value['orig_from'] = $value['from']; + $value['from'] = null; + } + + return $value; + } + + /** + * Prepare "from" value + * + * @param array $value + * @return array + */ + protected function prepareTo(array $value) + { + if (isset($value['to']) && empty($value['to']) && $value['to'] !== '0') { + $value['orig_to'] = $value['to']; + $value['to'] = null; + } + + return $value; + } +} diff --git a/app/code/Magento/Ui/Component/Filters/Type/Select.php b/app/code/Magento/Ui/Component/Filters/Type/Select.php new file mode 100644 index 0000000000000000000000000000000000000000..399ad004d5bbb1a72814d16b697315d34d34c84f --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters/Type/Select.php @@ -0,0 +1,128 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Filters\Type; + +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Ui\Component\Form\Element\Select as ElementSelect; + +/** + * Class Select + */ +class Select extends AbstractFilter +{ + const NAME = 'filter_select'; + + const COMPONENT = 'select'; + + /** + * Wrapped component + * + * @var ElementSelect + */ + protected $wrappedComponent; + + /** + * @var OptionSourceInterface + */ + protected $optionsProvider; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param OptionSourceInterface $optionsProvider + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + OptionSourceInterface $optionsProvider = null, + array $components = [], + array $data = [] + ) { + $this->optionsProvider = $optionsProvider; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + static::COMPONENT, + ['context' => $this->getContext(), 'options' => $this->optionsProvider] + ); + $this->wrappedComponent->prepare(); + + $this->applyFilter(); + $jsConfig = array_replace_recursive( + $this->getConfiguration($this->wrappedComponent), + $this->getConfiguration($this) + ); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Get JS config + * + * @return array + */ + public function getJsConfig() + { + return array_replace_recursive( + (array) $this->wrappedComponent->getData('config'), + (array) $this->getData('config') + ); + } + + /** + * Get condition by data type + * + * @return array|null + */ + public function getCondition() + { + $value = isset($this->filterData[$this->getName()]) ? $this->filterData[$this->getName()] : null; + $condition = null; + if (!empty($value) || is_numeric($value)) { + $condition = ['eq' => $value]; + } + + return $condition; + } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } +} diff --git a/app/code/Magento/Ui/Component/Form.php b/app/code/Magento/Ui/Component/Form.php index 4e4435b6773638f14a510253edf655d196508f6a..aa74ffddd3ecabb5967b7aac173534e1ed03ce71 100644 --- a/app/code/Magento/Ui/Component/Form.php +++ b/app/code/Magento/Ui/Component/Form.php @@ -5,222 +5,75 @@ */ namespace Magento\Ui\Component; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Framework\View\Element\UiElementFactory; -use Magento\Ui\Component\Control\ActionPool; -use Magento\Ui\Component\Control\ButtonProviderFactory; -use Magento\Ui\Component\Control\ButtonProviderInterface; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; /** * Class Form - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Form extends AbstractView +class Form extends AbstractComponent { - /** - * Default form element - */ - const DEFAULT_FORM_ELEMENT = 'input'; + const NAME = 'form'; /** - * From element map + * Get component name * - * @var array - */ - protected $formElementMap = [ - 'text' => 'input', - 'number' => 'input', - ]; - - /** - * Ui element builder - * - * @var ElementRendererBuilder - */ - protected $elementRendererBuilder; - - /** - * @var UiElementFactory - */ - protected $factory; - - /** - * @var ActionPool - */ - protected $actionPool; - - /** - * @var ButtonProviderFactory - */ - protected $buttonProviderFactory; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param ElementRendererBuilder $elementRendererBuilder - * @param UiElementFactory $factory - * @param ActionPool $actionPool - * @param ButtonProviderFactory $buttonProviderFactory - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @return string */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - ElementRendererBuilder $elementRendererBuilder, - UiElementFactory $factory, - ActionPool $actionPool, - ButtonProviderFactory $buttonProviderFactory, - array $data = [] - ) { - $this->elementRendererBuilder = $elementRendererBuilder; - $this->factory = $factory; - $this->actionPool = $actionPool; - $this->buttonProviderFactory = $buttonProviderFactory; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); + public function getComponentName() + { + return static::NAME; } /** - * Prepare component data + * Register component * * @return void */ public function prepare() { - $this->registerComponents(); - $buttons = $this->getData('buttons'); - if ($buttons) { - foreach ($buttons as $buttonId => $buttonClass) { - /** @var ButtonProviderInterface $button */ - $button = $this->buttonProviderFactory->create($buttonClass); - $buttonData = $button->getButtonData(); - if (!$buttonData) { - unset($buttons[$buttonId]); - continue; - } - $buttons[$buttonId] = $buttonData; - } - uasort($buttons, [$this, 'sortButtons']); - foreach ($buttons as $buttonId => $buttonData) { - $this->actionPool->add($buttonId, $buttonData, $this); - } - } + parent::prepare(); - $layoutSettings = (array) $this->getData('layout'); - $data = [ - 'name' => $this->getData('name'), - 'label' => $this->getData('label'), - 'data_sources' => $this->getData('data_sources'), - 'child_blocks' => $this->getLayout()->getChildBlocks($this->getNameInLayout()), - 'configuration' => isset($layoutSettings['configuration']) - ? $layoutSettings['configuration'] - : [], - ]; - $layoutType = isset($layoutSettings['type']) - ? $layoutSettings['type'] - : \Magento\Ui\Component\Layout\Tabs::NAME; - $layout = $this->factory->create( - $layoutType, - $data - ); - $layout->prepare(); - $this->elements[] = $layout; - } + $jsConfig = $this->getConfiguration($this); + unset($jsConfig['extends']); + $this->getContext()->addComponentDefinition($this->getContext()->getNamespace(), $jsConfig); - /** - * @return string - */ - public function getDataScope() - { - return $this->getData('name'); + $this->getContext()->addButtons($this->getData('buttons'), $this); } /** - * Register all UI Components configuration - * - * @return void + * @return array */ - protected function registerComponents() + public function getDataSourceData() { - $this->renderContext->getStorage()->addComponent( - $this->getData('name'), - [ - 'component' => 'Magento_Ui/js/form/component', - 'config' => [ - 'provider' => $this->getData('name'), - ], - 'deps' => [$this->getData('name')] - ] - ); - foreach ($this->getLayout()->getAllBlocks() as $name => $block) { - if ($block instanceof \Magento\Framework\View\Element\UiComponentInterface) { - $config = (array)$block->getData('js_config'); - if (!isset($config['extends'])) { - $config['extends'] = $this->getData('name'); + $dataSources = []; + foreach ($this->getChildComponents() as $component) { + if ($component instanceof DataSourceInterface) { + $dataProvider = $component->getDataProvider(); + $id = $this->getContext()->getRequestParam($dataProvider->getRequestFieldName()); + $preparedData = []; + if ($id) { + $dataProvider->addFilter($dataProvider->getPrimaryFieldName(), $id); + $preparedData = $dataProvider->getData(); + if (isset($preparedData[$id])) { + $preparedData = ['data' => $preparedData[$id]]; + } } - $this->renderContext->getStorage()->addComponent($name, $config); - } - }; - } - - /** - * @return string - */ - public function getSaveAction() - { - return $this->getUrl('mui/form/save'); - } - /** - * @return string - */ - public function getValidateAction() - { - return $this->getUrl('mui/form/validate'); - } - - /** - * Sort buttons by sort order - * - * @param array $itemA - * @param array $itemB - * @return int - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function sortButtons(array $itemA, array $itemB) - { - $sortOrderA = isset($itemA['sort_order']) ? intval($itemA['sort_order']) : 0; - $sortOrderB = isset($itemB['sort_order']) ? intval($itemB['sort_order']) : 0; - if ($sortOrderA == $sortOrderB) { - return 0; + $config = $dataProvider->getConfigData(); + if (isset($config['submit_url'])) { + $config['submit_url'] = $this->getContext()->getUrl($config['submit_url']); + } + if (isset($config['validate_url'])) { + $config['validate_url'] = $this->getContext()->getUrl($config['validate_url']); + } + $dataSources[$component->getName()] = [ + 'type' => $component->getComponentName(), + 'name' => $component->getName(), + 'dataScope' => $component->getContext()->getNamespace(), + 'config' => array_merge($preparedData, $config) + ]; + } } - return ($sortOrderA < $sortOrderB) ? -1 : 1; + return $dataSources; } } diff --git a/app/code/Magento/Ui/Component/Form/Collection.php b/app/code/Magento/Ui/Component/Form/Collection.php index 09b67401aaced6f231d871c1e004ed78113e80b3..c816843578c6b2ba80fcdbfea017d713031b0dac 100644 --- a/app/code/Magento/Ui/Component/Form/Collection.php +++ b/app/code/Magento/Ui/Component/Form/Collection.php @@ -5,13 +5,23 @@ */ namespace Magento\Ui\Component\Form; +use Magento\Ui\Component\AbstractComponent; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\Component\AbstractView; /** * Class Collection */ -class Collection extends AbstractView implements UiComponentInterface +class Collection extends AbstractComponent implements UiComponentInterface { - // + const NAME = 'collection'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/AbstractFormElement.php b/app/code/Magento/Ui/Component/Form/Element/AbstractElement.php similarity index 75% rename from app/code/Magento/Ui/Component/Form/Element/AbstractFormElement.php rename to app/code/Magento/Ui/Component/Form/Element/AbstractElement.php index e536143ab6b4a719b6e8582159d748eb1bc8d182..c01990b9d7e8eec7b59844c8f92d6d9bd6e67726 100644 --- a/app/code/Magento/Ui/Component/Form/Element/AbstractFormElement.php +++ b/app/code/Magento/Ui/Component/Form/Element/AbstractElement.php @@ -5,12 +5,12 @@ */ namespace Magento\Ui\Component\Form\Element; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** - * Class AbstractFormElement + * Class AbstractElement */ -abstract class AbstractFormElement extends AbstractView implements ElementInterface +abstract class AbstractElement extends AbstractComponent implements ElementInterface { /** * @return string @@ -38,9 +38,8 @@ abstract class AbstractFormElement extends AbstractView implements ElementInterf /** * @return bool - * @SuppressWarnings(PHPMD.BooleanGetMethodName) */ - public function getIsReadonly() + public function isReadonly() { return (bool) $this->getData('readonly'); } diff --git a/app/code/Magento/Ui/Component/Form/Element/Checkbox.php b/app/code/Magento/Ui/Component/Form/Element/Checkbox.php index df26d8c21bb31ba861c4d929b070e5854b917ab7..e3e73495628c2671d23c72ea725ed6da25916f55 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Checkbox.php +++ b/app/code/Magento/Ui/Component/Form/Element/Checkbox.php @@ -8,7 +8,30 @@ namespace Magento\Ui\Component\Form\Element; /** * Class Checkbox */ -class Checkbox extends AbstractFormElement +class Checkbox extends AbstractElement { - // + const NAME = 'checkbox'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getConfiguration($this, Input::NAME); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php b/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php index cc196dea37d70c3b3b0ff57e77e4d3ee40e5fc31..e36e3f3589ad6b119aba9ac2d1fd1436c1dc09e7 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php @@ -5,26 +5,20 @@ */ namespace Magento\Ui\Component\Form\Element\DataType; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class AbstractDataType */ -abstract class AbstractDataType extends AbstractView implements DataTypeInterface +abstract class AbstractDataType extends AbstractComponent implements DataTypeInterface { /** + * Validate value + * * @return bool */ public function validate() { return true; } - - /** - * @return string - */ - public function getDataObjectValue() - { - return $this->getData('data_object')[$this->getData('name')]; - } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php index 8fe4b24f502d9fc7ae0bb70027164dd42715d951..d7865d61e608eae19c3f72bdd63fe2998179953f 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php @@ -10,5 +10,15 @@ namespace Magento\Ui\Component\Form\Element\DataType; */ class Boolean extends AbstractDataType { - // + const NAME = 'boolean'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php b/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php index 63aefa0b72903f3bf46b029b6046426c356f6193..04bbecb0a8de5b2082931292b5ece267a77cc077 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php @@ -5,7 +5,6 @@ */ namespace Magento\Ui\Component\Form\Element\DataType; -use Magento\Framework\Object; use Magento\Framework\View\Element\UiComponentInterface; /** @@ -19,11 +18,4 @@ interface DataTypeInterface extends UiComponentInterface * @return bool */ public function validate(); - - /** - * Get data object value - * - * @return mixed - */ - public function getDataObjectValue(); } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php index 46bd9267d737c7c65b9584101277e8b7845bdd67..e72be53246d1698337ca34784304cf7801e59a33 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php @@ -5,10 +5,109 @@ */ namespace Magento\Ui\Component\Form\Element\DataType; +use Magento\Framework\Locale\ResolverInterface; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + /** * Class Date */ class Date extends AbstractDataType { - // + const NAME = 'date'; + + /** + * Current locale + * + * @var string + */ + protected $locale; + + /** + * Wrapped component + * + * @var UiComponentInterface + */ + protected $wrappedComponent; + + /** + * Constructor + * + * @param ContextInterface $context + * @param TimezoneInterface $localeDate + * @param ResolverInterface $localeResolver + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + TimezoneInterface $localeDate, + ResolverInterface $localeResolver, + array $components = [], + array $data = [] + ) { + $this->locale = $localeResolver->getLocale(); + $this->localeDate = $localeDate; + parent::__construct($context, $components, $data); + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $config = $this->getData('config'); + if (!isset($config['dateFormat'])) { + $config['dateFormat'] = $this->localeDate->getDateTimeFormat(\IntlDateFormatter::MEDIUM); + $this->setData('config', $config); + } + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + + /** + * Get locale + * + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Convert given date to default (UTC) timezone + * + * @param int $date + * @return \DateTime|null + */ + public function convertDate($date) + { + try { + $dateObj = $this->localeDate->date(new \DateTime($date), $this->getLocale(), false); + $dateObj->setTime(0, 0, 0); + //convert store date to default date in UTC timezone without DST + $dateObj->setTimezone(new \DateTimeZone('UTC')); + return $dateObj; + } catch (\Exception $e) { + return null; + } + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php index 7dda21c016ae980f741b1d98396c23e1a8ac8bb0..49b12bbf6277076373c277ed92f873828d99707e 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php @@ -10,5 +10,15 @@ namespace Magento\Ui\Component\Form\Element\DataType; */ class Email extends AbstractDataType { - // + const NAME = 'email'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php index 0f361470f944bc0956bdbdd1b61e0ba1e1050da7..fda46d7b137a0168884f6df5f38656127a8e7755 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php @@ -10,5 +10,15 @@ namespace Magento\Ui\Component\Form\Element\DataType; */ class Media extends AbstractDataType { - // + const NAME = 'media'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php index 4b5d7924e53c234d953efac46c438d3a6afc102c..929a86ab19a8a12b9694d3b9d546e3e4ce23680e 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php @@ -10,5 +10,15 @@ namespace Magento\Ui\Component\Form\Element\DataType; */ class Number extends AbstractDataType { - // + const NAME = 'number'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php index d58d74bd4c9d9ce839cd98e90e9b5bdac459f5dc..77a93da72288bfa57e0f8f20711461cd1ff4395a 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php @@ -10,5 +10,15 @@ namespace Magento\Ui\Component\Form\Element\DataType; */ class Password extends AbstractDataType { - // + const NAME = 'password'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php index 138c224dea80d65aa506d19691d479b80a02bdf5..a183fc4ad1760c3059baf1a37b50dede49e1cbb6 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php @@ -10,5 +10,15 @@ namespace Magento\Ui\Component\Form\Element\DataType; */ class Price extends AbstractDataType { - // + const NAME = 'price'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php index 43c259b510bcde506b3a41bbdb8876ae1fd20b8a..c3187b92a7706dd1bc89e830b53205755262483a 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php @@ -10,5 +10,15 @@ namespace Magento\Ui\Component\Form\Element\DataType; */ class Text extends AbstractDataType { - // + const NAME = 'text'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/ElementInterface.php b/app/code/Magento/Ui/Component/Form/Element/ElementInterface.php index f6cd906ed59ec2b3113b6513f3d33e4bd88d2755..3450d6238384ecb7298d7ed642b1bccfa218e19c 100644 --- a/app/code/Magento/Ui/Component/Form/Element/ElementInterface.php +++ b/app/code/Magento/Ui/Component/Form/Element/ElementInterface.php @@ -24,9 +24,8 @@ interface ElementInterface extends UiComponentInterface /** * @return bool - * @SuppressWarnings(PHPMD.BooleanGetMethodName) */ - public function getIsReadonly(); + public function isReadonly(); /** * @return string diff --git a/app/code/Magento/Ui/Component/Form/Element/Input.php b/app/code/Magento/Ui/Component/Form/Element/Input.php index 9d149e9dd290f4dd12712501d1ce778cc9007860..9b43d1b7db952c7907ac8e0152a8b345ff26efb5 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Input.php +++ b/app/code/Magento/Ui/Component/Form/Element/Input.php @@ -8,21 +8,30 @@ namespace Magento\Ui\Component\Form\Element; /** * Class Input */ -class Input extends AbstractFormElement +class Input extends AbstractElement { + const NAME = 'input'; + /** - * @return mixed|string + * Get component name + * + * @return string */ - public function getType() + public function getComponentName() { - return $this->getData('input_type') ? $this->getData('input_type') : 'text'; + return static::NAME; } /** + * Prepare component configuration + * * @return void */ public function prepare() { - parent::prepare(); // TODO: Change the autogenerated stub + parent::prepare(); + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } } diff --git a/app/code/Magento/Ui/Component/Form/Element/Multiline.php b/app/code/Magento/Ui/Component/Form/Element/Multiline.php index 5e8b3b226dcb0bb8827f12809f9d10c756542e29..de3cd8900ddd5c6fdac0ead4735637226ea578e0 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Multiline.php +++ b/app/code/Magento/Ui/Component/Form/Element/Multiline.php @@ -8,8 +8,20 @@ namespace Magento\Ui\Component\Form\Element; /** * Class Multiline */ -class Multiline extends AbstractFormElement +class Multiline extends AbstractElement { + const NAME = 'multiline'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return mixed|string */ @@ -19,10 +31,15 @@ class Multiline extends AbstractFormElement } /** + * Prepare component configuration + * * @return void */ public function prepare() { - parent::prepare(); // TODO: Change the autogenerated stub + parent::prepare(); + + $jsConfig = $this->getConfiguration($this, Input::NAME); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } } diff --git a/app/code/Magento/Ui/Component/Form/Element/Radio.php b/app/code/Magento/Ui/Component/Form/Element/Radio.php index 1737d460db14218d51e0edad5542b86c716a4723..1f93d43aa4fc16083193d5b8138bb4267eddba59 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Radio.php +++ b/app/code/Magento/Ui/Component/Form/Element/Radio.php @@ -8,8 +8,20 @@ namespace Magento\Ui\Component\Form\Element; /** * Class Radio */ -class Radio extends AbstractFormElement +class Radio extends AbstractElement { + const NAME = 'radio'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return bool * @SuppressWarnings(PHPMD.BooleanGetMethodName) diff --git a/app/code/Magento/Ui/Component/Form/Element/Range.php b/app/code/Magento/Ui/Component/Form/Element/Range.php index 549b295108c339afb4ca0170af0b76f1e4ae6195..debd3e1acabaa187c0482a73133b972ccecd6ca1 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Range.php +++ b/app/code/Magento/Ui/Component/Form/Element/Range.php @@ -8,8 +8,20 @@ namespace Magento\Ui\Component\Form\Element; /** * Class Range */ -class Range extends AbstractFormElement +class Range extends AbstractElement { + const NAME = 'range'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return mixed */ diff --git a/app/code/Magento/Ui/Component/Form/Element/Select.php b/app/code/Magento/Ui/Component/Form/Element/Select.php index 59a366d3e4b2aac3a270c2e41cefa9e2e4e1e1f1..be31eb6acad7955d8cd5757464282834bb016877 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Select.php +++ b/app/code/Magento/Ui/Component/Form/Element/Select.php @@ -5,11 +5,75 @@ */ namespace Magento\Ui\Component\Form\Element; +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + /** * Class Select */ -class Select extends AbstractFormElement +class Select extends AbstractElement { + const NAME = 'select'; + + /** + * @var array|OptionSourceInterface|null + */ + protected $options; + + /** + * Constructor + * + * @param ContextInterface $context + * @param array|OptionSourceInterface|null $options + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + $options = null, + array $components = [], + array $data = [] + ) { + $this->options = $options; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $config = $this->getData('config'); + if (isset($this->options)) { + if (!isset($config['options'])) { + $config['options'] = []; + } + if ($this->options instanceof OptionSourceInterface) { + $options = $this->options->toOptionArray(); + } else { + $options = array_values($this->options); + } + $config['options'] = array_values(array_merge_recursive($options, $config['options'])); + } + $this->setData('config', (array)$config); + + $jsConfig = $this->getConfiguration($this, Input::NAME); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + /** * Check if option value * diff --git a/app/code/Magento/Ui/Component/Form/Element/Textarea.php b/app/code/Magento/Ui/Component/Form/Element/Textarea.php index 0b7031ef8f6ce2dd7a6e76dcc810469704ff2d74..d7f12580d67d5c6b4f68c22a437f7cc28f228af6 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Textarea.php +++ b/app/code/Magento/Ui/Component/Form/Element/Textarea.php @@ -8,7 +8,30 @@ namespace Magento\Ui\Component\Form\Element; /** * Class Textarea */ -class Textarea extends AbstractFormElement +class Textarea extends AbstractElement { - // + const NAME = 'textarea'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getConfiguration($this, Input::NAME); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } } diff --git a/app/code/Magento/Ui/Component/Form/Field.php b/app/code/Magento/Ui/Component/Form/Field.php index 5f0c94dd42d765eb405c94b154e0c0956c10010d..890288d086a2a9c22ca51bb912391e6e220a42b5 100644 --- a/app/code/Magento/Ui/Component/Form/Field.php +++ b/app/code/Magento/Ui/Component/Form/Field.php @@ -5,29 +5,107 @@ */ namespace Magento\Ui\Component\Form; +use Magento\Framework\Exception\LocalizedException; +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\Component\AbstractView; +use Magento\Framework\View\Element\UiComponent\ContextInterface; /** - * Class AbstractFormElement + * Class Field */ -class Field extends AbstractView implements UiComponentInterface +class Field extends AbstractComponent { + const NAME = 'field'; + + /** + * Wrapped component + * + * @var UiComponentInterface + */ + protected $wrappedComponent; + + /** + * UI component factory + * + * @var UiComponentFactory + */ + protected $uiComponentFactory; + /** - * @return mixed + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param UiComponentInterface[] $components + * @param array $data */ - public function renderHeader() + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + array $components = [], + array $data = [] + ) { + $this->uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() { - return $this->getRenderEngine()->render($this, $this->getHeaderTemplate()); + return 'form.' . $this->wrappedComponent->getComponentName(); } /** - * Getting template for field header section + * Prepare component configuration * - * @return string|false + * @return void + * @throws \Magento\Framework\Exception\LocalizedException */ - public function getHeaderTemplate() + public function prepare() { - return isset($this->configuration['header_template']) ? $this->configuration['header_template'] : false; + parent::prepare(); + $formElement = $this->getData('config/formElement'); + if (null === $formElement) { + throw new LocalizedException(__( + 'The configuration parameter "formElement" is a required for "' . $this->getName() . '" field.' + )); + } + // Create of wrapped component + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + $formElement, + array_merge(['context' => $this->getContext()], (array) $this->getData()) + ); + $this->wrappedComponent->prepare(); + + // To prepare the component configuration + $wrappedComponentConfig = $this->getConfiguration($this->wrappedComponent); + $jsConfig = array_replace_recursive( + $wrappedComponentConfig, + $this->getConfiguration($this, $this->wrappedComponent->getComponentName()) + ); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Get JS config + * + * @return array + */ + public function getJsConfig() + { + if (isset($this->wrappedComponent)) { + return array_replace_recursive( + (array) $this->wrappedComponent->getData('config'), + (array) $this->getData('config') + ); + } + + return (array) $this->getData('config'); } } diff --git a/app/code/Magento/Ui/Component/Form/Fieldset.php b/app/code/Magento/Ui/Component/Form/Fieldset.php index 03fd8f62d6e847ba154c2390de4cde80732dcca0..f8d9ee0b012330a138d9d5cbb4ce743d07aef753 100644 --- a/app/code/Magento/Ui/Component/Form/Fieldset.php +++ b/app/code/Magento/Ui/Component/Form/Fieldset.php @@ -5,14 +5,19 @@ */ namespace Magento\Ui\Component\Form; -use Magento\Ui\Component\AbstractView; +use Magento\Framework\Exception\LocalizedException; +use Magento\Ui\Component\Container; +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; /** * Class Fieldset */ -class Fieldset extends AbstractView +class Fieldset extends AbstractComponent { - const UI_ELEMENT_FIELDSET = 'fieldset'; + const NAME = 'fieldset'; /** * @var bool @@ -20,43 +25,125 @@ class Fieldset extends AbstractView protected $collapsible = false; /** + * @var UiComponentInterface[] + */ + protected $fieldsInContainers = []; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param UiComponentInterface[] $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + array $components = [], + array $data = [] + ) { + $this->uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * * @return string */ - public function getLegendText() + public function getComponentName() { - return $this->getData('config/label'); + return static::NAME; } /** - * @return bool - * @SuppressWarnings(PHPMD.BooleanGetMethodName) + * Prepare component configuration + * + * @return void */ - public function getIsCollapsible() + public function prepare() { - return $this->getData('config/collapsible', $this->collapsible); + parent::prepare(); + foreach ($this->getChildComponents() as $name => $child) { + if ($child instanceof Container) { + $this->fieldsInContainers += $child->getChildComponents(); + } + } + + $fieldsMeta = $this->getContext()->getDataProvider()->getFieldsMetaInfo($this->getName()); + foreach ($fieldsMeta as $name => $fieldData) { + if (empty($fieldData)) { + continue; + } + $fieldComponent = $this->getComponent($name); + $this->prepareField($fieldData, $name, $fieldComponent); + } + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } /** - * @return string + * Prepare field component + * + * @param array $fieldData + * @param string $name + * @param UiComponentInterface|null $fieldComponent + * @return void + * @throws \Magento\Framework\Exception\LocalizedException */ - public function getAjaxUrl() + protected function prepareField(array $fieldData, $name, UiComponentInterface $fieldComponent = null) { - return $this->getData('config/source'); + if ($fieldComponent === null) { + if (isset($this->fieldsInContainers[$name])) { + $this->updateField($fieldData, $this->fieldsInContainers[$name]); + return; + } + $fieldData = $this->updateDataScope($fieldData, $name); + $argument = [ + 'context' => $this->getContext(), + 'data' => [ + 'name' => $name, + 'config' => $fieldData + ] + ]; + $fieldComponent = $this->uiComponentFactory->create($name, 'field', $argument); + $fieldComponent->prepare(); + $this->addComponent($name, $fieldComponent); + } else { + $this->updateField($fieldData, $fieldComponent); + } } /** - * @return string + * Update field data + * + * @param array $fieldData + * @param UiComponentInterface $component + * @return void */ - public function getContent() + protected function updateField(array $fieldData, UiComponentInterface $component) { - return $this->getData('config/content'); + $config = $component->getData('config'); + // XML data configuration override configuration coming from the DB + $config = array_replace_recursive($fieldData, $config); + $config = $this->updateDataScope($config, $component->getName()); + $component->setData('config', $config); } /** + * Update DataScope + * + * @param array $data + * @param string $name * @return array */ - public function getChildren() + protected function updateDataScope(array $data, $name) { - return $this->getData('children'); + if (!isset($data['dataScope'])) { + $data['dataScope'] = $name; + } + return $data; } } diff --git a/app/code/Magento/Ui/Component/Form/Fieldset/Factory.php b/app/code/Magento/Ui/Component/Form/Fieldset/Factory.php index f0b10c0b2dd618c161023307a70cab513e245849..191778de59da1f7813cedb6fa4f7daff481bc477 100644 --- a/app/code/Magento/Ui/Component/Form/Fieldset/Factory.php +++ b/app/code/Magento/Ui/Component/Form/Fieldset/Factory.php @@ -5,8 +5,8 @@ */ namespace Magento\Ui\Component\Form\Fieldset; -use Magento\Framework\ObjectManagerInterface; use Magento\Ui\Component\Form\Fieldset; +use Magento\Framework\ObjectManagerInterface; /** * Class Factory diff --git a/app/code/Magento/Ui/Component/Layout.php b/app/code/Magento/Ui/Component/Layout.php new file mode 100644 index 0000000000000000000000000000000000000000..369701019290432daf1a8e3fc31d7cf0166a4843 --- /dev/null +++ b/app/code/Magento/Ui/Component/Layout.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component; + +use Magento\Ui\Component\Layout\LayoutPool; +use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\UiComponent\LayoutInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + +/** + * Class Layout + */ +class Layout extends AbstractComponent +{ + const NAME = 'layout'; + + /** + * @var LayoutPool + */ + protected $layoutPool; + + /** + * @var string + */ + protected $type; + + /** + * @var LayoutInterface + */ + protected $layoutTypeObject; + + /** + * @var array + */ + protected $structure = []; + + /** + * Constructor + * + * @param ContextInterface $context + * @param LayoutPool $layoutPool + * @param string $type + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + LayoutPool $layoutPool, + $type, + array $components = [], + array $data = [] + ) { + $this->layoutPool = $layoutPool; + $this->type = $type; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Register component and build layout structure + * + * @inheritdoc + */ + public function prepare() + { + $this->layoutTypeObject = $this->layoutPool->create($this->type); + $this->structure = $this->layoutTypeObject->build($this); + } + + /** + * @return array + */ + public function getStructure() + { + return $this->structure; + } +} diff --git a/app/code/Magento/Ui/Component/Layout/AbstractStructure.php b/app/code/Magento/Ui/Component/Layout/AbstractStructure.php deleted file mode 100644 index 8fdd8616b7c8b2b22eb3b2b390e06d3d534ed9b8..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Layout/AbstractStructure.php +++ /dev/null @@ -1,564 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Layout; - -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Framework\View\Element\UiElementFactory; -use Magento\Ui\Component\AbstractView; -use Magento\Ui\Component\Layout\Tabs\TabInterface; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; -use Magento\Ui\DataProvider\Metadata; - -/** - * Class AbstractStructure - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class AbstractStructure extends AbstractView -{ - /** - * @var array - */ - protected $structure = [ - 'sections' => [], - 'areas' => [], - 'groups' => [], - 'elements' => [], - ]; - - /** - * @var UiElementFactory - */ - protected $factory; - - /** - * Layout Namespace - * - * @var string - */ - protected $ns; - - /** - * @var int - */ - protected $sortInc = 10; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param UiElementFactory $factory - * @param array $data - */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - UiElementFactory $factory, - array $data = [] - ) { - $this->factory = $factory; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); - } - - /** - * @inheritdoc - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - public function prepare() - { - $this->ns = $this->getData('name'); - - $this->initSections(); - $this->initAreas(); - $this->initGroups(); - $this->initElements(); - - foreach ($this->getDataSources() as $name => $dataSourceConfig) { - $this->processDataSource($dataSourceConfig); - } - - $this->processChildBLocks(); - - $this->renderContext->getStorage()->addLayoutStructure( - $this->getDataScope(), - [ - 'children' => $this->structure - ] - ); - - $navBlock = $this->factory->create( - \Magento\Ui\Component\Layout\Tabs\Nav::NAME, - [ - 'data_scope' => $this->ns - ] - ); - if ($this->getData('configuration/tabs_container_name')) { - $this->getRenderContext()->getPageLayout() - ->addBlock($navBlock, 'tabs_nav', $this->getData('configuration/tabs_container_name')); - } else { - $this->getRenderContext()->getPageLayout() - ->addBlock($navBlock, 'tabs_nav', 'content'); - } - } - - /** - * @return string - */ - public function getDataScope() - { - return $this->ns; - } - - /** - * Prepare initial structure for sections - * - * @return void - */ - protected function initSections() - { - $this->structure['sections'] = [ - 'type' => \Magento\Ui\Component\Layout\Tabs\Nav::NAME, - 'config' => [ - 'label' => $this->getData('label'), - ], - 'children' => [], - ]; - } - - /** - * Prepare initial structure for areas - * - * @return void - */ - protected function initAreas() - { - $this->structure['areas'] = [ - 'type' => 'form', - 'config' => [ - 'namespace' => $this->ns, - ], - 'children' => [], - ]; - } - - /** - * Prepare initial structure for groups - * - * @return void - */ - protected function initGroups() - { - $this->structure['groups'] = [ - 'children' => [], - ]; - } - - /** - * Prepare initial structure for elements - * - * @return void - */ - protected function initElements() - { - $this->structure['elements'] = [ - 'children' => [], - ]; - } - - /** - * Get registered Data Sources - * - * @return array - */ - protected function getDataSources() - { - return $this->getData('data_sources'); - } - - /** - * @param array $dataSourceConfig - * @return void - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - protected function processDataSource(array $dataSourceConfig) - { - $id = $this->renderContext->getRequestParam('id'); - $dataSource = $dataSourceConfig['name']; - - $meta = $this->dataManager->getMetadata($dataSource); - - $this->addArea( - $dataSource, - [ - 'insertTo' => [ - $this->ns . '.sections' => [ - 'position' => $this->getNextSortInc(), - ], - ], - 'config' => [ - 'label' => $meta->getLabel(), - ] - ] - ); - $referenceGroupName = $this->addGroup( - $dataSource, - [ - 'label' => $meta->getLabel() - ] - ); - - $elements = $meta->getFields(); - uasort($elements, [$this, 'sortChildren']); - foreach ($elements as $name => $element) { - if (isset($element['visible']) && $element['visible'] === 'false') { - continue; - } - if ($name != Metadata::CHILD_DATA_SOURCES) { - $collection = & $this->structure['elements']; - $this->addElementToCollection($collection, $name, "{$dataSource}.{$name}", $element); - - $referenceName = "{$this->ns}.elements.{$name}"; - $this->addElementToGroup($dataSource, $name, $referenceName, $element); - } - } - - $this->addToArea($dataSource, $referenceGroupName); - - $children = $meta->get(Metadata::CHILD_DATA_SOURCES); - foreach ($children as $childName => $childMeta) { - $this->processChildDataSource($dataSource, $childName, $childMeta); - } - - $preparedData = []; - $data = $id ? $this->dataManager->getData($dataSource, ['entity_id' => $id]) : []; - if ($data) { - $preparedData[$dataSource] = []; - foreach (array_shift($data) as $key => $value) { - $preparedData[$dataSource][$key] = $value; - } - } - - $this->renderContext->getStorage()->addDataSource( - $this->getData('name'), - [ - 'data' => $preparedData, - 'config' => $dataSourceConfig, - ] - ); - } - - /** - * @param string $dataSource - * @param string $childName - * @param \Magento\Ui\DataProvider\Metadata $childMeta - * @return void - */ - protected function processChildDataSource($dataSource, $childName, \Magento\Ui\DataProvider\Metadata $childMeta) - { - $this->addArea( - $childName, - [ - 'insertTo' => [ - $this->ns . '.sections' => [ - 'position' => $this->getNextSortInc(), - ], - ], - 'config' => [ - 'label' => $childMeta->getLabel(), - ] - ] - ); - $referenceChildGroupName = $this->addGroup( - $childName, - [ - 'label' => $childMeta->getLabel() - ] - ); - $this->addToArea($childName, $referenceChildGroupName); - - $itemTemplate = [ - 'type' => $this->ns, - 'isTemplate' => true, - 'component' => 'Magento_Ui/js/form/components/collection/item', - 'childType' => 'group', - 'config' => [ - 'label' => __('New ' . $childMeta->getLabel()), - ], - ]; - - $elements = $childMeta->getFields(); - uasort($elements, [$this, 'sortChildren']); - foreach ($elements as $name => $element) { - if (isset($element['visible']) && $element['visible'] === 'false') { - continue; - } - $this->addElementToCollection($itemTemplate, $name, $name, $element); - } - - $referenceCollectionName = $this->addCollection( - $childName . 'Collection', - "{$dataSource}.{$childName}", - [ - 'active' => 1, - 'label' => $childMeta->getLabel(), - 'removeLabel' => __('Remove ' . $childMeta->getLabel()), - 'removeMessage' => __('Are you sure you want to delete this item?'), - 'addLabel' => __('Add New ' . $childMeta->getLabel()), - 'itemTemplate' => 'item_template' - ] - ); - $this->addTemplateToCollection($childName . 'Collection', 'item_template', $itemTemplate); - - $this->structure['groups']['children'][$childName]['children'][] = $referenceCollectionName; - } - - /** - * @throws \Exception - * @return void - */ - protected function processChildBlocks() - { - //Add child blocks content - foreach ($this->getData('child_blocks') as $blockName => $childBlock) { - /** @var TabInterface $childBlock */ - if (!($childBlock instanceof TabInterface)) { - throw new \Exception(__('"%1" tab should implement TabInterface', $blockName)); - } - if (!$childBlock->canShowTab()) { - continue; - } - $childBlock->setData('target_form', $this->getDataScope()); - $sortOrder = $childBlock->hasSortOrder() ? $childBlock->getSortOrder() : $this->getNextSortInc(); - $this->addArea( - $blockName, - [ - 'insertTo' => [ - $this->ns . '.sections' => [ - 'position' => (int)$sortOrder, - ], - ], - 'config' => [ - 'label' => $childBlock->getTabTitle(), - ] - ] - ); - - $config = [ - 'label' => $childBlock->getTabTitle(), - ]; - if ($childBlock->isAjaxLoaded()) { - $config['source'] = $childBlock->getTabUrl(); - } else { - $config['content'] = $childBlock->toHtml(); - } - $referenceGroupName = $this->addGroup($blockName, $config, 'html_content'); - $this->addToArea($blockName, $referenceGroupName); - } - } - - /** - * @param string $name - * @param array $config - * @return string - */ - protected function addArea($name, array $config = []) - { - $config['type'] = 'tab'; - $this->structure['areas']['children'][$name] = $config; - return "{$this->ns}.areas.{$name}"; - } - - /** - * @param string $areaName - * @param string $itemName - * @return void - */ - protected function addToArea($areaName, $itemName) - { - $this->structure['areas']['children'][$areaName]['children'][] = $itemName; - } - - /** - * @param string $groupName - * @param array $config - * @param string $type - * @return string - */ - protected function addGroup($groupName, array $config = [], $type = 'fieldset') - { - $this->structure['groups']['children'][$groupName] = [ - 'type' => $type, - 'config' => $config, - ]; - return "{$this->ns}.groups.{$groupName}"; - } - - /** - * @param string $groupName - * @param string $elementName - * @param string $referenceElementName - * @param array $element - * @return void - */ - protected function addElementToGroup($groupName, $elementName, $referenceElementName, array $element) - { - if (isset($element['fieldGroup'])) { - if ($elementName === $element['fieldGroup']) { - $this->structure['groups']['children'][$groupName]['children'][] = $referenceElementName; - } - } else { - $this->structure['groups']['children'][$groupName]['children'][] = $referenceElementName; - } - } - - /** - * @param array $collection - * @param string $elementName - * @param string $dataScope - * @param array $element - * @return string - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function addElementToCollection(array & $collection, $elementName, $dataScope, array $element) - { - $collection['children'][$elementName] = [ - 'type' => 'group', - ]; - if (isset($element['fieldGroup'])) { - $elementName = $element['fieldGroup']; - if ($elementName === $element['fieldGroup']) { - $collection['children'][$elementName]['config'] = [ - 'displayArea' => $element['displayArea'], - ]; - } - } else { - $collection['children'][$elementName]['config'] = [ - 'displayArea' => $element['displayArea'], - ]; - } - - if (isset($element['constraints'])) { - if (isset($element['constraints']['validate'])) { - $element['validation'] = $element['constraints']['validate']; - } - if (isset($element['constraints']['filter'])) { - foreach ($element['constraints']['filter'] as $filter) { - $element['listeners'] = [ - "data:" . $filter['on'] => [ - 'filter' => [$filter['by']], - ], - ]; - } - } - unset($element['constraints']); - } - if (isset($element['size'])) { - $collection['children'][$elementName]['dataScope'] = $dataScope; - $size = (int)$element['size']; - for ($i = 0; $i < $size; $i++) { - $collection['children'][$elementName]['children'][] = [ - 'type' => $element['formElement'], - 'dataScope' => (string)$i, - 'config' => $element, - ]; - if (isset($element['validation']['required-entry'])) { - unset($element['validation']['required-entry']); - } - } - } else { - $collection['children'][$elementName]['children'][] = [ - 'type' => $element['formElement'], - 'dataScope' => $dataScope, - 'config' => $element, - ]; - } - } - - /** - * @param string $collectionName - * @param string $dataScope - * @param array $config - * @return string - */ - protected function addCollection($collectionName, $dataScope, array $config = []) - { - $this->structure['groups']['children'][$collectionName] = [ - 'type' => 'collection', - 'dataScope' => $dataScope, - 'config' => $config, - ]; - return "{$this->ns}.groups.{$collectionName}"; - } - - /** - * @param string $collectionName - * @param string $templateName - * @param array $template - * @return void - */ - protected function addTemplateToCollection($collectionName, $templateName, $template) - { - $this->structure['groups']['children'][$collectionName]['children'][$templateName] = $template; - } - - /** - * @return int - */ - protected function getNextSortInc() - { - $this->sortInc += 10; - return $this->sortInc; - } - - /** - * Sort child elements - * - * @param array $one - * @param array $two - * @return int - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function sortChildren(array $one, array $two) - { - if (!isset($one['sortOrder'])) { - return 1; - } - if (!isset($two['sortOrder'])) { - return -1; - } - $sortOrderA = isset($one['sortOrder']) ? intval($one['sortOrder']) : -1; - $sortOrderB = isset($two['sortOrder']) ? intval($two['sortOrder']) : -1; - if ($sortOrderA == $sortOrderB) { - return 0; - } - return ($sortOrderA < $sortOrderB) ? -1 : 1; - } -} diff --git a/app/code/Magento/Ui/Component/Layout/Generator/Structure.php b/app/code/Magento/Ui/Component/Layout/Generator/Structure.php new file mode 100644 index 0000000000000000000000000000000000000000..c26b9c40664a3bd93122a7f6bee509264fcb8049 --- /dev/null +++ b/app/code/Magento/Ui/Component/Layout/Generator/Structure.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Layout\Generator; + +use Magento\Ui\Component\Layout\LayoutPool; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\LayoutInterface; + +/** + * Class Structure + */ +class Structure +{ + /** + * @var LayoutPool + */ + protected $layoutPool; + + /** + * Constructor + * + * @param LayoutPool $layoutPool + */ + public function __construct(LayoutPool $layoutPool) + { + $this->layoutPool = $layoutPool; + } + + /** + * Build component structure and retrieve + * + * @param UiComponentInterface $component + * @return array + */ + public function generate(UiComponentInterface $component) + { + /** @var LayoutInterface $layout */ + if (!$layoutDefinition = $component->getData('layout')) { + $layoutDefinition = ['type' => 'generic']; + } + $layout = $this->layoutPool->create($layoutDefinition['type'], $layoutDefinition); + + return $layout->build($component); + } +} diff --git a/app/code/Magento/Ui/Component/Layout/Generic.php b/app/code/Magento/Ui/Component/Layout/Generic.php new file mode 100644 index 0000000000000000000000000000000000000000..04b0fbabe28de22f1799aa4dc43bd1740022e3bf --- /dev/null +++ b/app/code/Magento/Ui/Component/Layout/Generic.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Layout; + +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; +use Magento\Framework\View\Element\UiComponent\JsConfigInterface; +use Magento\Framework\View\Element\UiComponent\LayoutInterface; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Generic + */ +class Generic implements LayoutInterface +{ + /** + * Generate Java Script configuration element + * + * @param UiComponentInterface $component + * @return array + */ + public function build(UiComponentInterface $component) + { + $children = []; + $context = $component->getContext(); + $this->addChildren($children, $component, $component->getName()); + $dataSources = $component->getDataSourceData(); + $configuration = [ + 'types' => $context->getComponentsDefinitions(), + 'components' => [ + $context->getNamespace() => [ + 'children' => array_merge($children, $dataSources) + ] + ] + ]; + return $configuration; + } + + /** + * Add children data + * + * @param array $topNode + * @param UiComponentInterface $component + * @param string $componentType + * @return void + */ + protected function addChildren( + array &$topNode, + UiComponentInterface $component, + $componentType + ) { + $childrenNode = []; + $childComponents = $component->getChildComponents(); + if (!empty($childComponents)) { + /** @var UiComponentInterface $child */ + foreach ($childComponents as $child) { + if ($child instanceof DataSourceInterface) { + continue; + } + self::addChildren($childrenNode, $child, $child->getComponentName()); + } + } + /** @var JsConfigInterface $component */ + $config = $component->getJsConfig(); + if (is_string($config)) { + $topNode[] = $config; + } else { + $nodeData = [ + 'type' => $componentType, + 'name' => $component->getName(), + ]; + if (!empty($childrenNode)) { + $nodeData['children'] = $childrenNode; + } + if (isset($config['dataScope'])) { + $nodeData['dataScope'] = $config['dataScope']; + unset($config['dataScope']); + } + if (!empty($config)) { + $nodeData['config'] = $config; + } + $topNode[] = $nodeData; + } + } +} diff --git a/app/code/Magento/Ui/Component/Layout/Group.php b/app/code/Magento/Ui/Component/Layout/Group.php deleted file mode 100644 index 4b3eb842c56f9805ae8647c3376b4334ead92199..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Layout/Group.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Layout; - -use Magento\Ui\Component\AbstractView; - -/** - * Class Group - */ -class Group extends AbstractView -{ - /** - * @return string - */ - public function getIsRequired() - { - return $this->getData('required') ? 'required' : ''; - } -} diff --git a/app/code/Magento/Ui/Component/Layout/LayoutPool.php b/app/code/Magento/Ui/Component/Layout/LayoutPool.php new file mode 100644 index 0000000000000000000000000000000000000000..b15a513ff42c604797718731bb16798f670b95a4 --- /dev/null +++ b/app/code/Magento/Ui/Component/Layout/LayoutPool.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Layout; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Element\UiComponent\LayoutInterface; + +/** + * Class LayoutPool + */ +class LayoutPool +{ + const DEFAULT_CLASS = 'Magento\Ui\Component\Layout\Generic'; + + /** + * Layouts pool + * + * @var array + */ + protected $types; + + /** + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + * @param array $types + */ + public function __construct( + ObjectManagerInterface $objectManager, + array $types = [] + ) { + $this->objectManager = $objectManager; + $this->types = $types; + } + + /** + * Get layout by type + * + * @param string $layoutType + * @param array $arguments + * @return LayoutInterface + */ + public function create($layoutType, array $arguments = []) + { + if (!isset($this->types[$layoutType])) { + throw new \InvalidArgumentException(sprintf('Unknown layout type "%s"', $layoutType)); + } + $defArgs = $this->types[$layoutType]; + $class = isset($defArgs['class']) ? $defArgs['class'] : self::DEFAULT_CLASS; + unset($defArgs['class']); + if ($defArgs) { + $arguments = array_merge($defArgs, $arguments); + } + return $this->objectManager->create($class, $arguments); + } +} diff --git a/app/code/Magento/Ui/Component/Layout/Tabs.php b/app/code/Magento/Ui/Component/Layout/Tabs.php index d56881d3904c3b2f8134020ffbc59b3f7b93f506..ffdfc631486b59dff94fa9b0538e32af9b72641f 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs.php @@ -5,13 +5,396 @@ */ namespace Magento\Ui\Component\Layout; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\View\Element\Template; +use Magento\Ui\Component\Layout\Tabs\TabInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\LayoutInterface; +use Magento\Framework\View\Element\UiComponent\JsConfigInterface; /** * Class Tabs - * - * @package Magento\Ui\Component\Layout */ -class Tabs extends AbstractStructure +class Tabs extends Generic implements LayoutInterface { - const NAME = 'tabs'; + /** + * @var string + */ + protected $navContainerName; + + /** + * @var UiComponentInterface + */ + protected $component; + + /** + * @var string + */ + protected $namespace; + + /** + * @var array + */ + protected $structure = []; + + /** + * @var int + */ + protected $sortIncrement = 10; + + /** + * @var UiComponentFactory + */ + protected $uiComponentFactory; + + /** + * Constructor + * + * @param UiComponentFactory $uiComponentFactory + * @param null|string $navContainerName + */ + public function __construct(UiComponentFactory $uiComponentFactory, $navContainerName = null) + { + $this->navContainerName = $navContainerName; + $this->uiComponentFactory = $uiComponentFactory; + } + + /** + * Build + * + * @param UiComponentInterface $component + * @return array + */ + public function build(UiComponentInterface $component) + { + $this->component = $component; + $this->namespace = $component->getContext()->getNamespace(); + + $this->addNavigationBlock(); + + // Initialization of structure components + $this->initSections(); + $this->initAreas(); + + return parent::build($component); + } + + /** + * Add children data + * + * @param array $topNode + * @param UiComponentInterface $component + * @param string $componentType + * @return void + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function addChildren(array &$topNode, UiComponentInterface $component, $componentType) + { + $childrenAreas = []; + $collectedComponents = []; + + foreach ($component->getContext()->getDataProvider()->getMeta() as $name => $meta) { + $childComponent = $component->getComponent($name); + if (null === $childComponent) { + continue; + } + $collectedComponents[$childComponent->getName()] = true; + + if (isset($meta['is_collection']) && $meta['is_collection'] === true) { + $label = $childComponent->getData('config/label'); + $this->component->getContext()->addComponentDefinition( + 'collection', + [ + 'component' => 'Magento_Ui/js/form/components/collection', + 'extends' => $this->namespace + ] + ); + + /** + * @var UiComponentInterface $childComponent + * @var array $structure + */ + list($childComponent, $structure) = $this->prepareChildComponents($childComponent, $name); + + $childrenStructure = $structure[$name]['children']; + + $structure[$name]['children'] = [ + $name . '_collection' => [ + 'type' => 'collection', + 'config' => [ + 'active' => 1, + 'removeLabel' => __('Remove ' . $label), + 'addLabel' => __('Add New ' . $label), + 'removeMessage' => $childComponent->getData('config/removeMessage'), + 'itemTemplate' => 'item_template', + ], + 'children' => [ + 'item_template' => ['type' => $this->namespace, + 'isTemplate' => true, + 'component' => 'Magento_Ui/js/form/components/collection/item', + 'childType' => 'group', + 'config' => [ + 'label' => __('New ' . $label), + ], + 'children' => $childrenStructure + ] + ] + ] + ]; + } else { + /** + * @var UiComponentInterface $childComponent + * @var array $structure + */ + list($childComponent, $structure) = $this->prepareChildComponents($childComponent, $name); + } + + $tabComponent = $this->createTabComponent($childComponent, $name); + + $childrenAreas[$name] = [ + 'type' => $tabComponent->getComponentName(), + 'dataScope' => 'data.' . $name, + 'config' => isset($meta['config']) ? $meta['config'] : [], + 'insertTo' => [ + $this->namespace . '.sections' => [ + 'position' => $this->getNextSortIncrement() + ] + ], + 'children' => $structure, + ]; + } + + $this->addWrappedBlock($childrenAreas, $component, $collectedComponents); + + $this->structure[static::AREAS_KEY]['children'] = $childrenAreas; + $topNode = $this->structure; + } + + /** + * Add wrapped layout block + * + * @param array $areas + * @param UiComponentInterface $component + * @param array $collectedComponents + * @return void + */ + protected function addWrappedBlock(array &$areas, UiComponentInterface $component, array $collectedComponents) + { + /** @var \Magento\Ui\Component\Wrapper\Block $childComponent */ + foreach ($component->getChildComponents() as $name => $childComponent) { + /** @var TabInterface $block */ + $block = $childComponent->getBlock(); + if (isset($collectedComponents[$name]) || !($block instanceof TabInterface) || !$block->canShowTab()) { + continue; + } + $block->setData('target_form', $this->namespace); + + $config = []; + if ($block->isAjaxLoaded()) { + $config['url'] = $block->getTabUrl(); + } else { + $config['content'] = $block->toHtml(); + } + + $tabComponent = $this->createTabComponent($childComponent, $name); + $areas[$name] = [ + 'type' => $tabComponent->getComponentName(), + 'dataScope' => $name, + 'insertTo' => [ + $this->namespace . '.sections' => [ + 'position' => $block->hasSortOrder() ? $block->getSortOrder() : $this->getNextSortIncrement() + ] + ], + 'config' => [ + 'label' => $block->getTabTitle() + ], + 'children' => [ + $name => [ + 'type' => 'html_content', + 'dataScope' => $name, + 'config' => $config, + ] + ], + ]; + } + + $this->component->getContext()->addComponentDefinition( + 'html_content', + [ + 'component' => 'Magento_Ui/js/form/components/html', + 'extends' => $this->namespace + ] + ); + } + + /** + * Create tab component + * + * @param UiComponentInterface $childComponent + * @param string $name + * @return UiComponentInterface + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function createTabComponent(UiComponentInterface $childComponent, $name) + { + $tabComponent = $this->uiComponentFactory->create( + $name, + 'tab', + [ + 'context' => $this->component->getContext(), + 'components' => [$childComponent->getName() => $childComponent] + ] + ); + $tabComponent->prepare(); + $this->component->addComponent($name, $tabComponent); + + return $tabComponent; + } + + /** + * To prepare the structure of child components + * + * @param UiComponentInterface $component + * @param string $parentName + * @return array + */ + protected function prepareChildComponents(UiComponentInterface $component, $parentName) + { + $name = $component->getName(); + $childComponents = $component->getChildComponents(); + + $childrenStructure = []; + foreach ($childComponents as $childName => $child) { + $isVisible = $child->getData('config/visible'); + if ($isVisible !== null && $isVisible == 0) { + continue; + } + /** + * @var UiComponentInterface $childComponent + * @var array $childStructure + */ + list($childComponent, $childStructure) = $this->prepareChildComponents($child, $component->getName()); + $childrenStructure = array_merge($childrenStructure, $childStructure); + $component->addComponent($childName, $childComponent); + } + + $structure = [ + $name => [ + 'type' => $component->getComponentName(), + 'name' => $component->getName(), + 'children' => $childrenStructure + ] + ]; + + /** @var JsConfigInterface $component */ + list($config, $dataScope) = $this->prepareConfig((array) $component->getJsConfig(), $name, $parentName); + + if ($dataScope !== false) { + $structure[$name]['dataScope'] = $dataScope; + } + $structure[$name]['config'] = $config; + + return [$component, $structure]; + } + + /** + * Prepare config + * + * @param array $config + * @param string $name + * @param string $parentName + * @return array + */ + protected function prepareConfig(array $config, $name, $parentName) + { + $dataScope = false; + if (!isset($config['displayArea'])) { + $config['displayArea'] = 'body'; + } + if (isset($config['dataScope'])) { + $dataScope = $config['dataScope']; + unset($config['dataScope']); + } else if ($name !== $parentName) { + $dataScope = $name; + } + + return [$config, $dataScope]; + } + + /** + * Prepare initial structure for sections + * + * @return void + */ + protected function initSections() + { + $this->structure[static::SECTIONS_KEY] = [ + 'type' => 'nav', + 'config' => [ + 'label' => $this->component->getData('label'), + ], + 'children' => [], + ]; + } + + /** + * Prepare initial structure for areas + * + * @return void + */ + protected function initAreas() + { + $this->structure[static::AREAS_KEY] = [ + 'type' => $this->namespace, + 'config' => [ + 'namespace' => $this->namespace, + ], + 'children' => [], + ]; + } + + /** + * Add navigation block + * + * @return void + */ + protected function addNavigationBlock() + { + $pageLayout = $this->component->getContext()->getPageLayout(); + /** @var \Magento\Ui\Component\Layout\Tabs\Nav $navBlock */ + if (isset($this->navContainerName)) { + $navBlock = $pageLayout->addBlock( + 'Magento\Ui\Component\Layout\Tabs\Nav', + 'tabs_nav', + $this->navContainerName + ); + } else { + $navBlock = $pageLayout->addBlock('Magento\Ui\Component\Layout\Tabs\Nav', 'tabs_nav', 'content'); + } + $navBlock->setTemplate('Magento_Ui::layout/tabs/nav/default.phtml'); + $navBlock->setData('data_scope', $this->namespace); + + $this->component->getContext()->addComponentDefinition( + 'nav', + [ + 'component' => 'Magento_Ui/js/form/components/tab_group', + 'config' => [ + 'template' => 'ui/tab' + ], + 'extends' => $this->namespace + ] + ); + } + + /** + * Get next sort increment + * + * @return int + */ + protected function getNextSortIncrement() + { + $this->sortIncrement += 10; + return $this->sortIncrement; + } } diff --git a/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php b/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php index 885eb69e277de40df6f7d45d4c41928840ea6385..7c93e19f9a0d8653927119f5d8a94d205e41c59c 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php @@ -5,12 +5,12 @@ */ namespace Magento\Ui\Component\Layout\Tabs; -use Magento\Ui\Component\AbstractView; +use Magento\Framework\View\Element\Template; /** * Class Nav */ -class Nav extends AbstractView +class Nav extends Template { - const NAME = 'nav'; + // } diff --git a/app/code/Magento/Ui/Component/Layout/Tabs/Tab.php b/app/code/Magento/Ui/Component/Layout/Tabs/Tab.php index 4428717e8bc0774656adeaa07d8644e84f49efc0..ac3c530df89b7dcb80879a0c5a9c1a53cf447cd6 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs/Tab.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs/Tab.php @@ -5,21 +5,105 @@ */ namespace Magento\Ui\Component\Layout\Tabs; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class Tab */ -class Tab extends AbstractView +class Tab extends AbstractComponent implements TabInterface { + const NAME = 'tab'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Return Tab label + * + * @return string + */ + public function getTabLabel() + { + return $this->getData('tab_label'); + } + + /** + * Return Tab title + * + * @return string + */ + public function getTabTitle() + { + return $this->getData('tab_title'); + } + + /** + * Tab class getter + * + * @return string + */ + public function getTabClass() + { + return $this->getData('tab_class'); + } + /** - * Render content + * Return URL link to Tab content * - * @param array $data * @return string */ - public function render(array $data = []) + public function getTabUrl() + { + return $this->getData('tab_url'); + } + + /** + * Tab should be loaded trough Ajax call + * + * @return bool + */ + public function isAjaxLoaded() + { + return $this->getData('is_ajax_loaded'); + } + + /** + * Can show tab in tabs + * + * @return boolean + */ + public function canShowTab() + { + return $this->getData('can_show_tab'); + } + + /** + * Tab is hidden + * + * @return boolean + */ + public function isHidden() { - // + return $this->getData('is_hidden'); } } diff --git a/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php b/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php index 1e65e984b0732f219b72810c72ba7f68f2a0b05e..cb47ad3afabab2d54745e8ec276bbce32a648617 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php @@ -3,14 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Ui\Component\Layout\Tabs; /** - * Tab Interface - * - * @author Magento Core Team <core@magentocommerce.com> + * Interface TabInterface */ -namespace Magento\Ui\Component\Layout\Tabs; - interface TabInterface { /** diff --git a/app/code/Magento/Ui/Component/Layout/Tabs/TabWrapper.php b/app/code/Magento/Ui/Component/Layout/Tabs/TabWrapper.php index 6c0cd88e0a0d3397faf30676f44f537aa5989e66..bccdc5eda3c3da42fb423d13bfa734fad5521616 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs/TabWrapper.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs/TabWrapper.php @@ -3,11 +3,13 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Ui\Component\Layout\Tabs; use Magento\Framework\View\Element\Text\ListText; +/** + * Class TabWrapper + */ class TabWrapper extends ListText implements TabInterface { /** diff --git a/app/code/Magento/Ui/Component/Listing.php b/app/code/Magento/Ui/Component/Listing.php index 6d8437a886c5e531522c59fe1fae4e13f7461ab3..d84fd74cf278d59f688832bc2bc3bb1bfe114671 100644 --- a/app/code/Magento/Ui/Component/Listing.php +++ b/app/code/Magento/Ui/Component/Listing.php @@ -5,262 +5,102 @@ */ namespace Magento\Ui\Component; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\Control\ActionPool; -use Magento\Ui\Component\Listing\OptionsFactory; -use Magento\Ui\Component\Listing\RowPool; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; +use Magento\Ui\Component\Listing\Columns; +use Magento\Ui\Component\Listing\Columns\Column; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; /** * Class Listing - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Listing extends AbstractView +class Listing extends AbstractComponent { - /** - * Options provider key in data array - */ - const OPTIONS_PROVIDER_KEY = 'options_provider'; - - /** - * Row data provider key in data array - */ - const ROW_DATA_PROVIDER_KEY = 'row_data_provider'; - - /** - * Data provider row pool - * - * @var RowPool - */ - protected $dataProviderRowPool; - - /** - * Page action pool - * - * @var ActionPool - */ - protected $actionPool; + const NAME = 'listing'; /** - * Constructor + * Get component name * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param OptionsFactory $optionsFactory - * @param ActionPool $actionPool - * @param RowPool $dataProviderRowPool - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @return string */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - OptionsFactory $optionsFactory, - ActionPool $actionPool, - RowPool $dataProviderRowPool, - array $data = [] - ) { - $this->actionPool = $actionPool; - $this->optionsFactory = $optionsFactory; - $this->dataProviderRowPool = $dataProviderRowPool; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); + public function getComponentName() + { + return static::NAME; } /** - * Prepare custom data + * Register component and it's page main actions * * @return void */ public function prepare() { - $meta = $this->getMeta(); - $defaultConfigData = $this->getDefaultConfiguration(); - - if ($this->hasData('configuration')) { - $configData = $this->getData('configuration'); - if (!empty($configData['page_actions'])) { - foreach ($configData['page_actions'] as $key => $action) { - $defaultConfigData['page_actions'][$key] = isset($configData['page_actions']) - ? array_replace($defaultConfigData['page_actions'][$key], $configData['page_actions'][$key]) - : $defaultConfigData['page_actions'][$key]; - } - } - unset($configData['page_actions']); - $defaultConfigData = array_merge($defaultConfigData, $configData); - } - - foreach ($defaultConfigData['page_actions'] as $key => $action) { - $this->actionPool->add($key, $action, $this); - } - unset($defaultConfigData['page_actions']); - - $this->prepareConfiguration($defaultConfigData, $this->getData('name')); - $this->renderContext->getStorage()->addMeta($this->getData('name'), $meta); - $this->renderContext->getStorage()->addDataCollection($this->getData('name'), $this->getData('dataSource')); - } + parent::prepare(); - /** - * Render content - * - * @param array $data - * @return string - */ - public function render(array $data = []) - { - $this->initialConfiguration(); + $jsConfig = $this->getConfiguration($this); + unset($jsConfig['extends']); + $this->getContext()->addComponentDefinition($this->getContext()->getNamespace(), $jsConfig); - return parent::render($data); + $this->getContext()->addButtons($this->getData('buttons'), $this); } /** - * Get meta data - * - * @return array + * @inheritdoc */ - public function getMeta() + public function getDataSourceData() { - $meta = $this->getData('meta'); - foreach ($meta['fields'] as $key => $field) { - if ($field['data_type'] === 'date') { - $field['date_format'] = $this->_localeDate->getDateTimeFormat( - \IntlDateFormatter::MEDIUM - ); + $columns = $this->collectColumns(); + $dataSources = []; + foreach ($this->getChildComponents() as $component) { + // we need to process only Data Sources + if (!$component instanceof DataSourceInterface) { + continue; } - - if (isset($field[static::OPTIONS_PROVIDER_KEY])) { - $field['options'] = $this->optionsFactory->create($field[static::OPTIONS_PROVIDER_KEY]) - ->getOptions(empty($field['options']) ? [] : $field['options']); + $data = $component->getDataProvider()->getData(); + if (!empty($data['items']) && !empty($columns)) { + // Columns may need to pre-process data before using it + foreach ($columns as $column) { + $column->prepareItems($data['items']); + } } - unset($field[static::OPTIONS_PROVIDER_KEY]); - $meta['fields'][$key] = $field; - } - - return $meta; - } - - /** - * Apply data provider to row data - * - * @param array $dataRow - * @return array - */ - protected function getDataFromDataProvider(array $dataRow) - { - if ($this->hasData(static::ROW_DATA_PROVIDER_KEY)) { - foreach ($this->getData(static::ROW_DATA_PROVIDER_KEY) as $field => $data) { - $dataRow[$field] = $this->dataProviderRowPool->get($data['class'])->getData($dataRow, $data); - } + $dataSources[] = [ + 'type' => $component->getComponentName(), + 'name' => $component->getName(), + 'dataScope' => $component->getContext()->getNamespace(), + 'config' => array_replace_recursive( + [ + 'data' => $data, + 'totalCount' => $component->getDataProvider()->count(), + ], + (array) $component->getData('config'), + // ensure that namespace hasn't been overridden by accident + [ + 'params' => [ + 'namespace' => $this->getContext()->getNamespace() + ], + ] + ), + ]; } - - return $dataRow; + return $dataSources; } /** - * Get collection items + * Go through child components and collect Column types only. * - * @return array + * @return Column[] */ - public function getCollectionItems() + protected function collectColumns() { - $items = []; - $collection = $this->getDataCollection(); - foreach ($collection->getItems() as $item) { - $actualFields = []; - $itemsData = $this->getDataFromDataProvider($item->getData()); - foreach (array_keys($this->getData('meta/fields')) as $field) { - $actualFields[$field] = $itemsData[$field]; + $columns = []; + foreach ($this->getChildComponents() as $component) { + if ($component instanceof Columns) { + foreach ($component->getChildComponents() as $column) { + if ($column instanceof Column) { + $columns[] = $column; + } + } } - $items[] = $actualFields; } - - return $items; - } - - /** - * @return \Magento\Framework\Api\CriteriaInterface|\Magento\Framework\Data\CollectionDataSourceInterface - */ - protected function getDataCollection() - { - return $this->renderContext->getStorage()->getDataCollection($this->getName()); - } - - /** - * Configuration initialization - * - * @return void - */ - protected function initialConfiguration() - { - $url = $this->getUrl($this->getData('client_root')); - $this->renderContext->getStorage()->addGlobalData( - 'client', - [ - 'root' => $url, - 'ajax' => [ - 'data' => [ - 'component' => $this->getNameInLayout(), - ], - ] - ] - ); - $this->renderContext->getStorage()->addGlobalData('dump', ['extenders' => []]); - - $collection = $this->getDataCollection(); - $totalCount = $collection->count(); - $this->renderContext->getStorage()->addDataSource( - $this->getName(), - [ - 'data' => [ - 'meta_reference' => $this->getName(), - 'items' => $this->getCollectionItems(), - 'pages' => ceil($totalCount / $this->renderContext->getRequestParam('limit', 20)), - 'totalCount' => $totalCount, - ] - ] - ); - } - - /** - * Get default parameters - * - * @return array - */ - public function getDefaultConfiguration() - { - return [ - 'page_actions' => [ - 'add' => [ - 'name' => 'add', - 'label' => __('Add New'), - 'class' => 'primary', - 'url' => $this->getUrl('*/*/new'), - ], - ] - ]; + return $columns; } } diff --git a/app/code/Magento/Ui/Component/Listing/Columns.php b/app/code/Magento/Ui/Component/Listing/Columns.php new file mode 100644 index 0000000000000000000000000000000000000000..6e2eee1180af125d572fef1d048ad6435744f3f8 --- /dev/null +++ b/app/code/Magento/Ui/Component/Listing/Columns.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Listing; + +use Magento\Ui\Component\AbstractComponent; +use Magento\Ui\Component\Listing\Columns\Column; + +/** + * Class Columns + */ +class Columns extends AbstractComponent +{ + const NAME = 'columns'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + foreach ($this->getChildComponents() as $column) { + if ($column instanceof Column) { + $meta = $this->getContext()->getDataProvider()->getFieldMetaInfo($this->getName(), $column->getName()); + if ($meta) { + $config = $column->getData('config'); + $config = array_replace_recursive($config, $meta); + $column->setData('config', $config); + } + } + } + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } +} diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Column.php b/app/code/Magento/Ui/Component/Listing/Columns/Column.php new file mode 100644 index 0000000000000000000000000000000000000000..cda819b5f7d0cf61c9d65aa49dec99cba41d90bd --- /dev/null +++ b/app/code/Magento/Ui/Component/Listing/Columns/Column.php @@ -0,0 +1,136 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Listing\Columns; + +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + +/** + * Class Column + */ +class Column extends AbstractComponent implements ColumnInterface +{ + const NAME = 'column'; + + /** + * Wrapped component + * + * @var UiComponentInterface + */ + protected $wrappedComponent; + + /** + * UI component factory + * + * @var UiComponentFactory + */ + protected $uiComponentFactory; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + array $components = [], + array $data = [] + ) { + $this->uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME . '.' . $this->getData('config/dataType'); + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $dataType = $this->getData('config/dataType'); + $wrappedComponentConfig = []; + if ($dataType) { + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + $dataType, + array_merge(['context' => $this->getContext()], (array) $this->getData()) + ); + $this->wrappedComponent->prepare(); + $wrappedComponentConfig = $this->getConfiguration($this->wrappedComponent); + } + + $this->applySorting(); + $jsConfig = array_replace_recursive($wrappedComponentConfig, $this->getConfiguration($this)); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Get JS config + * + * @return array + */ + public function getJsConfig() + { + if (isset($this->wrappedComponent)) { + return array_replace_recursive( + (array) $this->wrappedComponent->getData('config'), + (array) $this->getData('config') + ); + } + + return (array) $this->getData('config'); + } + + /** + * To prepare items of a column + * + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + return $items; + } + + /** + * Apply sorting + * + * @return void + */ + protected function applySorting() + { + $sorting = $this->getContext()->getRequestParam('sorting'); + $isSortable = $this->getData('config/sortable'); + if ($isSortable !== false + && !empty($sorting['field']) + && !empty($sorting['direction']) + && $sorting['field'] === $this->getName() + ) { + $this->getContext()->getDataProvider()->addOrder( + $this->getName(), + strtoupper($sorting['direction']) + ); + } + } +} diff --git a/app/code/Magento/Ui/Component/Listing/Columns/ColumnInterface.php b/app/code/Magento/Ui/Component/Listing/Columns/ColumnInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0fb07d7e415f9a94089c7c0fe4468600e953aaf3 --- /dev/null +++ b/app/code/Magento/Ui/Component/Listing/Columns/ColumnInterface.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Listing\Columns; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface ColumnInterface + */ +interface ColumnInterface extends UiComponentInterface +{ + /** + * To prepare items of a column + * + * @param array $items + * @return array + */ + public function prepareItems(array & $items); +} diff --git a/app/code/Magento/Ui/Component/Listing/OptionsFactory.php b/app/code/Magento/Ui/Component/Listing/OptionsFactory.php deleted file mode 100644 index ab1e1c822f451e57e73737ea093ce742f87a169a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Listing/OptionsFactory.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Listing; - -use Magento\Framework\ObjectManagerInterface; - -/** - * Class OptionsFactory - */ -class OptionsFactory -{ - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * Constructor - * - * @param ObjectManagerInterface $objectManager - */ - public function __construct(ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * Getting provider object - * - * @param string $class - * @param array $arguments - * @return OptionsInterface - * @throws \InvalidArgumentException - */ - public function create($class, array $arguments = []) - { - $object = $this->objectManager->create($class, $arguments); - if (!($object instanceof OptionsInterface)) { - throw new \InvalidArgumentException( - sprintf('"%s" must implement the interface \Magento\Ui\Component\Listing\OptionsInterface', $class) - ); - } - - return $object; - } -} diff --git a/app/code/Magento/Ui/Component/Listing/OptionsInterface.php b/app/code/Magento/Ui/Component/Listing/OptionsInterface.php deleted file mode 100644 index 97ffc3d9c15f19373f518f445813abbee7afe343..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Listing/OptionsInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Listing; - -/** - * Class OptionsInterface - */ -interface OptionsInterface -{ - /** - * Get options - * - * @param array $options - * @return array - */ - public function getOptions(array $options = []); -} diff --git a/app/code/Magento/Ui/Component/Listing/RowPool.php b/app/code/Magento/Ui/Component/Listing/RowPool.php deleted file mode 100644 index 165eaef33ab3d2a8f1ef794b859095b7e9d95f3a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Listing/RowPool.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component\Listing; - -use Magento\Framework\ObjectManagerInterface; - -/** - * Class RowPool - */ -class RowPool -{ - /** - * @var RowInterface[] - */ - protected $classPool; - - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * Constructor - * - * @param ObjectManagerInterface $objectManager - */ - public function __construct(ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * Getting provider object - * - * @param string $class - * @param array $arguments - * @return RowInterface - * @throws \InvalidArgumentException - */ - public function get($class, array $arguments = []) - { - if (!isset($this->classPool[$class])) { - $this->classPool[$class] = $this->objectManager->create($class, $arguments); - if (!($this->classPool[$class] instanceof RowInterface)) { - throw new \InvalidArgumentException( - sprintf('"%s" must implement the interface \Magento\Ui\Component\Listing\RowInterface', $class) - ); - } - } - - return $this->classPool[$class]; - } -} diff --git a/app/code/Magento/Ui/Component/MassAction.php b/app/code/Magento/Ui/Component/MassAction.php index e892c9ed2793ef68bf535dea55721fc6f85f8092..140e48c0b15f3eb112d1e17b686f768f6da692ac 100644 --- a/app/code/Magento/Ui/Component/MassAction.php +++ b/app/code/Magento/Ui/Component/MassAction.php @@ -5,33 +5,51 @@ */ namespace Magento\Ui\Component; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + /** * Class MassAction */ -class MassAction extends AbstractView +class MassAction extends AbstractComponent { + const NAME = 'massaction'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** - * Prepare component data + * Register component * - * @return $this|void + * @return void */ public function prepare() { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); + $this->prepareConfiguration(); + $config = $this->getData('config'); + if (isset($config['actions'])) { + $config['actions'] = array_values($config['actions']); + array_walk_recursive( + $config['actions'], + function (&$item, $key, $context) { + /** @var ContextInterface $context */ + if ($key === 'url') { + $item = $context->getUrl($item); + } + }, + $this->getContext() + ); + $this->setData('config', $config); } - array_walk_recursive( - $configData, - function (&$item, $key, $object) { - if ($key === 'url') { - $item = $object->getUrl($item); - } - }, - $this - ); - $this->prepareConfiguration($configData); + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } /** diff --git a/app/code/Magento/Ui/Component/MassAction/Columns/Column.php b/app/code/Magento/Ui/Component/MassAction/Columns/Column.php new file mode 100644 index 0000000000000000000000000000000000000000..6e1e438782197597e4db7e1545bfe72406b91fd9 --- /dev/null +++ b/app/code/Magento/Ui/Component/MassAction/Columns/Column.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\MassAction\Columns; + +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\Component\Listing\Columns\ColumnInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + +/** + * Class Column + */ +class Column extends AbstractComponent implements ColumnInterface +{ + const NAME = 'column.massaction'; + + /** + * Wrapped component + * + * @var UiComponentInterface + */ + protected $wrappedComponent; + + /** + * UI component factory + * + * @var UiComponentFactory + */ + protected $uiComponentFactory; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + array $components = [], + array $data = [] + ) { + $this->uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Prepare items + * + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + return $items; + } +} diff --git a/app/code/Magento/Ui/Component/Paging.php b/app/code/Magento/Ui/Component/Paging.php index 7c504b74ac8303fff539ffe9671af8a9c68039e7..df104e0948771197d7e688671483e8197c3bc467 100644 --- a/app/code/Magento/Ui/Component/Paging.php +++ b/app/code/Magento/Ui/Component/Paging.php @@ -8,39 +8,80 @@ namespace Magento\Ui\Component; /** * Class Paging */ -class Paging extends AbstractView +class Paging extends AbstractComponent { + const NAME = 'paging'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** - * Prepare component data + * Register component and apply paging settings to Data Provider * * @return void */ public function prepare() { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } + parent::prepare(); + + $this->prepareConfiguration(); + $this->prepareOptions(); + + $paging = $this->getContext()->getRequestParam('paging'); + + $this->getContext()->getDataProvider()->setLimit($this->getOffset($paging), $this->getSize($paging)); + + $jsConfig = $this->getConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Get offset + * + * @param array|null $paging + * @return int + */ + protected function getOffset($paging) + { + $defaultPage = $this->getData('config/current') ?: 1; + return (int) (isset($paging['current']) ? $paging['current'] : $defaultPage); + } - $this->prepareConfiguration($configData); - $this->updateDataCollection(); + /** + * Get size + * + * @param array|null $paging + * @return int + */ + protected function getSize($paging) + { + $defaultLimit = $this->getData('config/pageSize') ?: 20; + return (int) (isset($paging['pageSize']) ? $paging['pageSize'] : $defaultLimit); } /** - * Update data collection + * Prepare paging options * * @return void */ - protected function updateDataCollection() + protected function prepareOptions() { - $defaultPage = $this->config->getData('current'); - $offset = $this->renderContext->getRequestParam('page', $defaultPage); - $defaultLimit = $this->config->getData('pageSize'); - $size = $this->renderContext->getRequestParam('limit', $defaultLimit); - $this->renderContext->getStorage() - ->getDataCollection($this->getParentName()) - ->setPageSize($size) - ->setCurPage($offset); + $config = $this->getData('config'); + if (isset($config['options'])) { + $config['options'] = array_values($config['options']); + foreach ($config['options'] as &$item) { + $item['value'] = (int) $item['value']; + } + unset($item); + $this->setData('config', $config); + } } /** @@ -51,7 +92,28 @@ class Paging extends AbstractView protected function getDefaultConfiguration() { return [ - 'sizes' => [20, 30, 50, 100, 200], + 'options' => [ + '20' => [ + 'value' => 20, + 'label' => 20 + ], + '30' => [ + 'value' => 30, + 'label' => 30 + ], + '50' => [ + 'value' => 50, + 'label' => 50 + ], + '100' => [ + 'value' => 100, + 'label' => 100 + ], + '200' => [ + 'value' => 200, + 'label' => 200 + ], + ], 'pageSize' => 20, 'current' => 1 ]; diff --git a/app/code/Magento/Ui/Component/RenderLayoutInterface.php b/app/code/Magento/Ui/Component/RenderLayoutInterface.php deleted file mode 100644 index 34bb85e8d7469fd0280c242b09906225995bb80d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/RenderLayoutInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -use Magento\Framework\View\Element\UiComponentInterface; - -/** - * Interface RenderLayoutInterface - */ -interface RenderLayoutInterface extends UiComponentInterface -{ -} diff --git a/app/code/Magento/Ui/Component/Search.php b/app/code/Magento/Ui/Component/Search.php deleted file mode 100644 index b32227b5561eb819fead4ab817637f25cfcc7abc..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Search.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -/** - * Class Search - */ -class Search extends AbstractView -{ - // -} diff --git a/app/code/Magento/Ui/Component/Sorting.php b/app/code/Magento/Ui/Component/Sorting.php deleted file mode 100644 index 944c8e531b3004400ca35e6a36b58ed84d3792ac..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Component/Sorting.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Component; - -/** - * Class Sorting - */ -class Sorting extends AbstractView -{ - /** - * Prepare component data - * - * @return void - */ - public function prepare() - { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - - $this->prepareConfiguration($configData); - $this->updateDataCollection(); - } - - /** - * Update data collection - * - * @return void - */ - protected function updateDataCollection() - { - $field = $this->config->getData('field'); - $direction = $this->config->getData('direction'); - if (!empty($field) && !empty($direction)) { - $this->renderContext->getStorage()->getDataCollection($this->getParentName())->addOrder( - $this->renderContext->getRequestParam('sort', $field), - strtoupper($this->renderContext->getRequestParam('dir', $direction)) - ); - } - } - - /** - * Get default parameters - * - * @return array - */ - protected function getDefaultConfiguration() - { - return ['direction' => 'asc']; - } -} diff --git a/app/code/Magento/Ui/Component/Wrapper/Block.php b/app/code/Magento/Ui/Component/Wrapper/Block.php new file mode 100644 index 0000000000000000000000000000000000000000..8f352313d94fd153ed1f10112970cc5f8bf18b0a --- /dev/null +++ b/app/code/Magento/Ui/Component/Wrapper/Block.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Wrapper; + +use Magento\Framework\View\Element\BlockInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Ui\Component\AbstractComponent; + +/** + * Class Block + */ +class Block extends AbstractComponent +{ + const NAME = 'blockWrapper'; + + /** + * @var BlockInterface + */ + protected $block; + + /** + * Constructor + * + * @param ContextInterface $context + * @param BlockInterface $block + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + BlockInterface $block, + array $components = [], + array $data = [] + ) { + $this->block = $block; + parent::__construct($context, $components, $data); + } + + /** + * Get wrapped block + * + * @return BlockInterface + */ + public function getBlock() + { + return $this->block; + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * @return string + */ + public function render() + { + return $this->block->toHtml(); + } +} diff --git a/app/code/Magento/Ui/Component/Wrapper/UiComponent.php b/app/code/Magento/Ui/Component/Wrapper/UiComponent.php new file mode 100644 index 0000000000000000000000000000000000000000..28f67161272ab1b44f59709a28379379e30178a1 --- /dev/null +++ b/app/code/Magento/Ui/Component/Wrapper/UiComponent.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Component\Wrapper; + +use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\ContainerInterface; +use Magento\Framework\View\Element\Template\Context as TemplateContext; + +/** + * Class UiComponent + * + * Encapsulate UI Component to represent it as standard Layout Block + */ +class UiComponent extends Template implements ContainerInterface +{ + /** + * Ui component + * + * @var UiComponentInterface + */ + protected $component; + + /** + * @var BlockFactory + */ + protected $blockWrapperFactory; + + /** + * Constructor + * + * @param TemplateContext $context + * @param UiComponentInterface $component + * @param BlockFactory $blockWrapperFactory + * @param array $data + */ + public function __construct( + TemplateContext $context, + UiComponentInterface $component, + BlockFactory $blockWrapperFactory, + array $data = [] + ) { + $this->component = $component; + $this->blockWrapperFactory = $blockWrapperFactory; + $this->setNameInLayout($this->component->getName()); + parent::__construct($context, $data); + } + + /** + * Render block HTML + * + * @return string + */ + protected function _toHtml() + { + foreach ($this->getChildNames() as $childName) { + $childBlock = $this->getLayout()->getBlock($childName); + if ($childBlock) { + $wrapper = $this->blockWrapperFactory->create([ + 'block' => $childBlock, + 'data' => [ + 'name' => 'block_' . $childName + ] + ]); + $this->component->addComponent('block_' . $childName, $wrapper); + } + } + + $result = $this->component->render(); + return (string)$result; + } +} diff --git a/app/code/Magento/Ui/ContentType/Builder/ConfigJson.php b/app/code/Magento/Ui/ContentType/Builder/ConfigJson.php deleted file mode 100644 index 74c3af86783591d5c34f50df4918cf1c4a8a2928..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/ContentType/Builder/ConfigJson.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\ContentType\Builder; - -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigInterface; - -/** - * Class ConfigJson - */ -class ConfigJson implements ConfigBuilderInterface -{ - /** - * Config data to JSON by output - * - * @param ConfigInterface $configuration - * @return string - */ - public function toJson(ConfigInterface $configuration) - { - $result = $configuration->getData(); - $result['name'] = $configuration->getName(); - $result['parent_name'] = $configuration->getParentName(); - - return json_encode($result); - } -} diff --git a/app/code/Magento/Ui/ContentType/Builder/ConfigStorageJson.php b/app/code/Magento/Ui/ContentType/Builder/ConfigStorageJson.php deleted file mode 100644 index 99eca8d2994345fba40b8769903002da11fac1a5..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/ContentType/Builder/ConfigStorageJson.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\ContentType\Builder; - -use Magento\Framework\View\Element\UiComponent\ConfigInterface; -use Magento\Framework\View\Element\UiComponent\ConfigStorageBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigStorageInterface; - -/** - * Class ConfigStorageBuilder - */ -class ConfigStorageJson implements ConfigStorageBuilderInterface -{ - /** - * Config storage data to JSON by output - * - * @param ConfigStorageInterface $storage - * @param string $parentName - * @return string - */ - public function toJson(ConfigStorageInterface $storage, $parentName = null) - { - $result = [ - 'config' => [], - ]; - $result['meta'] = $storage->getMeta($parentName); - $dataSource = $storage->getDataSource($parentName); - $data = isset($dataSource['data']) ? $dataSource['data'] : null; - if ($parentName !== null) { - $rootComponent = $storage->getComponentsData($parentName); - $result['name'] = $rootComponent->getName(); - $result['parent_name'] = $rootComponent->getParentName(); - $result['data'] = $data; - $result['config']['components'][$rootComponent->getName()] = $rootComponent->getData(); - } else { - $components = $storage->getComponentsData(); - if (!empty($components)) { - /** @var ConfigInterface $component */ - foreach ($components as $name => $component) { - $result['config']['components'][$name] = $component->getData(); - } - } - $result['data'] = $data; - } - $result['config'] += $storage->getGlobalData(); - $result['dump']['extenders'] = []; - - return json_encode($result); - } - - /** - * Config storage data to JSON by output - * - * @param ConfigStorageInterface $storage - * @return string - */ - public function toJsonNew(ConfigStorageInterface $storage) - { - $result = []; - foreach ($storage->getDataSource() as $name => $dataSource) { - $dataSource['path'] = 'Magento_Ui/js/form/provider'; - $result['providers'][$name] = $dataSource; - } - $result['renderer'] = [ - 'types' => $storage->getComponents(), - 'layout' => $storage->getLayoutStructure(), - ]; - return json_encode($result); - } -} diff --git a/app/code/Magento/Ui/ContentType/Html.php b/app/code/Magento/Ui/ContentType/Html.php deleted file mode 100644 index dee784fdbbd37f279a2ed6637cc9fa70a37e9cac..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/ContentType/Html.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\ContentType; - -use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Framework\View\FileSystem; -use Magento\Framework\View\TemplateEnginePool; - -/** - * Class Html - */ -class Html implements ContentTypeInterface -{ - /** - * @var \Magento\Framework\View\FileSystem - */ - protected $filesystem; - - /** - * @var \Magento\Framework\View\TemplateEnginePool - */ - protected $templateEnginePool; - - /** - * Constructor - * - * @param FileSystem $filesystem - * @param TemplateEnginePool $templateEnginePool - */ - public function __construct(FileSystem $filesystem, TemplateEnginePool $templateEnginePool) - { - $this->filesystem = $filesystem; - $this->templateEnginePool = $templateEnginePool; - } - - /** - * Render data - * - * @param UiComponentInterface $view - * @param string $template - * @return string - */ - public function render(UiComponentInterface $view, $template = '') - { - $templateEngine = false; - if ($template) { - $extension = pathinfo($template, PATHINFO_EXTENSION); - $templateEngine = $this->templateEnginePool->get($extension); - } - if ($templateEngine) { - $path = $this->filesystem->getTemplateFileName($template); - $result = $templateEngine->render($view, $path); - } else { - $result = ''; - } - return $result; - } -} diff --git a/app/code/Magento/Ui/ContentType/Json.php b/app/code/Magento/Ui/ContentType/Json.php deleted file mode 100644 index 4eb26e619a8311974f44615e1a3e448ccc7a1555..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/ContentType/Json.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\ContentType; - -use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Framework\View\FileSystem; -use Magento\Framework\View\TemplateEnginePool; - -/** - * Class Json - */ -class Json implements ContentTypeInterface -{ - /** - * @var \Magento\Framework\View\FileSystem - */ - protected $filesystem; - - /** - * @var \Magento\Framework\View\TemplateEnginePool - */ - protected $templateEnginePool; - - /** - * Constructor - * - * @param FileSystem $filesystem - * @param TemplateEnginePool $templateEnginePool - */ - public function __construct(FileSystem $filesystem, TemplateEnginePool $templateEnginePool) - { - $this->filesystem = $filesystem; - $this->templateEnginePool = $templateEnginePool; - } - - /** - * Render data - * - * @param UiComponentInterface $view - * @param string $template - * @return string - */ - public function render(UiComponentInterface $view, $template = '') - { - return $view->getRenderContext() - ->getConfigBuilder() - ->toJson($view->getRenderContext()->getStorage(), $view->getName()); - } -} diff --git a/app/code/Magento/Ui/Context/Configuration.php b/app/code/Magento/Ui/Context/Configuration.php deleted file mode 100644 index 7711fec456f00869c7b7771d7b6edc9556188034..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Context/Configuration.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Context; - -use Magento\Framework\View\Element\UiComponent\ConfigInterface; - -/** - * Class Configuration - */ -class Configuration implements ConfigInterface -{ - /** - * Configuration data - * - * @var array - */ - protected $configuration = []; - - /** - * Name of owner - * - * @var string - */ - protected $name; - - /** - * Name of parent owner - * - * @var string - */ - protected $parentName; - - /** - * Constructor - * - * @param string $name - * @param string $parentName - * @param array $configuration - */ - public function __construct($name, $parentName, $configuration = []) - { - $this->name = $name; - $this->parentName = $parentName; - $this->configuration = $configuration; - } - - /** - * Get configuration data - * - * @param string|null $key - * @return mixed - */ - public function getData($key = null) - { - if ($key === null) { - return (array)$this->configuration; - } - return isset($this->configuration[$key]) ? $this->configuration[$key] : null; - } - - /** - * Add configuration data - * - * @param string $key - * @param mixed $data - * @return mixed - */ - public function addData($key, $data) - { - if (!isset($this->configuration[$key])) { - $this->configuration[$key] = $data; - } - } - - /** - * Update configuration data - * - * @param string $key - * @param mixed $data - * @return mixed - */ - public function updateData($key, $data) - { - $this->configuration[$key] = $data; - } - - /** - * Get owner name - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Get owner parent name - * - * @return string - */ - public function getParentName() - { - return $this->parentName; - } -} diff --git a/app/code/Magento/Ui/Context/ConfigurationStorage.php b/app/code/Magento/Ui/Context/ConfigurationStorage.php deleted file mode 100644 index 91218f496e01087985d06a62a06df8184bc3de0e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Context/ConfigurationStorage.php +++ /dev/null @@ -1,340 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Context; - -use Magento\Framework\Data\CollectionDataSourceInterface; -use Magento\Framework\View\Element\UiComponent\ConfigInterface; -use Magento\Framework\View\Element\UiComponent\ConfigStorageInterface; -use Magento\Framework\View\Element\UiComponent\DataProviderInterface; - -/** - * Class ConfigurationStorage - */ -class ConfigurationStorage implements ConfigStorageInterface -{ - /** - * Components configuration storage - * - * @var array - */ - protected $componentStorage = []; - - /** - * Data storage - * - * @var array - */ - protected $dataStorage = []; - - /** - * Meta storage - * - * @var array - */ - protected $metaStorage = []; - - /** - * Data collection storage - * - * @var CollectionDataSourceInterface[] - */ - protected $collectionStorage = []; - - /** - * Global data storage - * - * @var array - */ - protected $globalDataStorage = []; - - /** - * Data provider storage - * - * @var array - */ - protected $dataProviderStorage = []; - - /** - * @var array - */ - protected $components = []; - - /** - * @var array - */ - protected $layoutStructure = []; - - /** - * @inheritdoc - */ - public function addComponent($name, $data) - { - $this->components[$name] = $data; - } - - /** - * @inheritdoc - */ - public function addComponentsData(ConfigInterface $config) - { - if (!isset($this->componentStorage[$config->getName()])) { - $this->componentStorage[$config->getName()] = $config; - } - } - - /** - * @return array - */ - public function getComponents() - { - return $this->components; - } - - /** - * @return array - */ - public function getMetaKeys() - { - return array_keys($this->metaStorage); - } - - /** - * @inheritdoc - */ - public function removeComponentsData(ConfigInterface $configuration) - { - unset($this->componentStorage[$configuration->getName()]); - } - - /** - * @inheritdoc - */ - public function getComponentsData($name = null) - { - if ($name === null) { - return $this->componentStorage; - } - return isset($this->componentStorage[$name]) ? $this->componentStorage[$name] : null; - } - - /** - * @inheritdoc - */ - public function addDataSource($name, array $dataSource) - { - if (!isset($this->dataStorage[$name])) { - $this->dataStorage[$name] = $dataSource; - } - } - - /** - * @inheritdoc - */ - public function removeDataSource($name) - { - unset($this->dataStorage[$name]); - } - - /** - * @inheritdoc - */ - public function getDataSource($name = null) - { - if ($name === null) { - return $this->dataStorage; - } - return isset($this->dataStorage[$name]) ? $this->dataStorage[$name] : null; - } - - /** - * @inheritdoc - */ - public function updateDataSource($name, array $dataSource) - { - if (isset($this->dataStorage[$name])) { - $this->dataStorage[$name] = $dataSource; - } - } - - /** - * @inheritdoc - */ - public function addMeta($key, array $data) - { - if (!isset($this->metaStorage[$key])) { - $this->metaStorage[$key] = $data; - } - } - - /** - * @inheritdoc - */ - public function removeMeta($key) - { - unset($this->metaStorage[$key]); - } - - /** - * @inheritdoc - */ - public function getMeta($key = null) - { - if ($key === null) { - return $this->metaStorage; - } - return isset($this->metaStorage[$key]) ? $this->metaStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function updateMeta($key, array $data) - { - if (isset($this->metaStorage[$key])) { - $this->metaStorage[$key] = $data; - } - } - - /** - * @inheritdoc - */ - public function addDataCollection($key, CollectionDataSourceInterface $dataCollection) - { - if (!isset($this->collectionStorage[$key])) { - $this->collectionStorage[$key] = $dataCollection; - } - } - - /** - * @inheritdoc - */ - public function getDataCollection($key = null) - { - if ($key === null) { - return $this->collectionStorage; - } - return isset($this->collectionStorage[$key]) ? $this->collectionStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function updateDataCollection($key, CollectionDataSourceInterface $dataCollection) - { - if (isset($this->collectionStorage[$key])) { - $this->collectionStorage[$key] = $dataCollection; - } - } - - /** - * @inheritdoc - */ - public function addGlobalData($key, array $data) - { - if (!isset($this->globalDataStorage[$key])) { - $this->globalDataStorage[$key] = $data; - } - } - - /** - * @inheritdoc - */ - public function removeGlobalData($key) - { - unset($this->globalDataStorage[$key]); - } - - /** - * @inheritdoc - */ - public function getGlobalData($key = null) - { - if ($key === null) { - return $this->globalDataStorage; - } - return isset($this->globalDataStorage[$key]) ? $this->globalDataStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function addDataProvider($key, DataProviderInterface $dataProvider) - { - if (!isset($this->dataProviderStorage[$key])) { - $this->dataProviderStorage[$key] = $dataProvider; - } - } - - /** - * @inheritdoc - */ - public function removeDataProvider($key) - { - if (isset($this->dataProviderStorage[$key])) { - unset($this->dataProviderStorage[$key]); - } - } - - /** - * @inheritdoc - */ - public function getDataProvider($key = null) - { - if ($key === null) { - return $this->dataProviderStorage; - } - return isset($this->dataProviderStorage[$key]) ? $this->dataProviderStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function updateDataProvider($key, DataProviderInterface $dataProvider) - { - if (isset($this->dataProviderStorage[$key])) { - $this->dataProviderStorage[$key] = $dataProvider; - } - } - - /** - * @inheritdoc - */ - public function addLayoutStructure($dataScope, array $structure) - { - $this->layoutStructure[$dataScope] = $structure; - } - - /** - * @inheritdoc - */ - public function getLayoutStructure() - { - return $this->layoutStructure; - } - - /** - * @inheritdoc - */ - public function getLayoutNode($name, $default = null) - { - if (strpos($name, '.') !== false) { - $nameParts = explode('.', $name); - $firstChunk = array_shift($nameParts); - $node = isset($this->layoutStructure[$firstChunk]) ? $this->layoutStructure[$firstChunk] : []; - foreach ($nameParts as $nodeName) { - if (isset($node['children'][$nodeName])) { - $node = $node['children'][$nodeName]; - } else { - $node = $default; - break; - } - } - } else { - $node = isset($this->layoutStructure[$name]) ? $this->layoutStructure[$name] : []; - } - return $node; - } -} diff --git a/app/code/Magento/Ui/Context/DataProvider.php b/app/code/Magento/Ui/Context/DataProvider.php deleted file mode 100644 index 1621470ec575263082f3ff569b560f721039e92b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Context/DataProvider.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Context; - -use Magento\Ui\Component\AbstractView; - -/** - * Class DataProvider - */ -class DataProvider extends AbstractView -{ - /** - * @return string - */ - public function getAsJson() - { - return $this->renderContext->getConfigBuilder()->toJson($this->renderContext->getStorage()); - } -} diff --git a/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php b/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php index 46a218025258c33dfd1f9d8425e57bc5dd6d8966..6893905b14938d6e9f4906cb9c205c8563c43244 100644 --- a/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php +++ b/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php @@ -1,19 +1,19 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Ui\Controller\Adminhtml; +use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; -use Magento\Framework\View\Element\UiComponentFactory; use Magento\Ui\Controller\UiActionInterface; +use Magento\Framework\View\Element\UiComponentFactory; /** * Class Render */ -abstract class AbstractAction extends \Magento\Backend\App\Action implements UiActionInterface +abstract class AbstractAction extends Action implements UiActionInterface { /** * @var UiComponentFactory diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Form/Fieldset.php b/app/code/Magento/Ui/Controller/Adminhtml/Form/Fieldset.php deleted file mode 100644 index 9c556c7191cdf6d854d146abea66c7c9586e7126..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Controller/Adminhtml/Form/Fieldset.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php -/** - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -namespace Magento\Ui\Controller\Adminhtml\Form; - -/** - * Class Fieldset - * - * @package Magento\Ui\Controller\Adminhtml\Form - */ -class Fieldset extends \Magento\Ui\Controller\Adminhtml\AbstractAction -{ - /** - * Action for AJAX request - * - * @return void - */ - public function execute() - { - // $component = $this->getComponent(); -// $name = $this->getName(); -// if ($component && $name) { -// $fieldset = $this->factory->createUiComponent($this->getComponent(), $this->getName())->getContainer($this->_request->getParam('container')); -// $fieldset->setNotLoadByAjax(); -// $this->_response->appendBody( -// $fieldset->render() -// ); -// } else { -// $this->_redirect('admin'); -// } -// $tabIndex = $this->getRequest()->getParam('container'); -// $this->getResponse()->appendBody( -// json_encode( -// ['layout' => ['customer_form_tabs' => [$tabIndex => ['label' => 'loaded', 'content' => 'content is loaded']]]] -// ) -// ); - } -} diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Form/Save.php b/app/code/Magento/Ui/Controller/Adminhtml/Form/Save.php deleted file mode 100644 index 27bcd9d5096c5243c8ce52f02106c573df457a66..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Controller/Adminhtml/Form/Save.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php -/** - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Controller\Adminhtml\Form; - -/** - * Class Save - * - * @package Magento\Ui\Controller\Adminhtml\Form - */ -class Save extends \Magento\Ui\Controller\Adminhtml\AbstractAction -{ - /** - * Action for AJAX request - * - * @return void - */ - public function execute() - { - $component = $this->getComponent(); - $name = $this->getName(); - if ($component && $name) { - $formElement = $this->factory->createUiComponent($component, $name); - list($module, $controller, $action) = explode('\\', $formElement->getSaveMca()); - $this->_forward($action, $controller, $module, $this->getRequest()->getParams()); - } else { - $this->_redirect('admin'); - } - } -} diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Form/Validate.php b/app/code/Magento/Ui/Controller/Adminhtml/Form/Validate.php deleted file mode 100644 index 2d55343ed1e1230ea9128a477931187926ab5b70..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Controller/Adminhtml/Form/Validate.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -/** - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Controller\Adminhtml\Form; - -class Validate extends \Magento\Ui\Controller\Adminhtml\AbstractAction -{ - /** - * Action for AJAX request - * - * @return void - */ - public function execute() - { - $component = $this->getComponent(); - $name = $this->getName(); - if ($component && $name) { - $formElement = $this->factory->createUiComponent($component, $name); - list($module, $controller, $action) = explode('\\', $formElement->getValidateMca()); - $this->_forward($action, $controller, $module, $this->getRequest()->getParams()); - } else { - $this->_redirect('admin'); - } - } -} diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Index/Render.php b/app/code/Magento/Ui/Controller/Adminhtml/Index/Render.php index bda4c09c8751aaf1185e3ee8a61a078bd8354f71..d7d89e88d378fc305dfd01ed98c8dbc00c22e933 100644 --- a/app/code/Magento/Ui/Controller/Adminhtml/Index/Render.php +++ b/app/code/Magento/Ui/Controller/Adminhtml/Index/Render.php @@ -1,18 +1,31 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Ui\Controller\Adminhtml\Index; +use Magento\Backend\App\Action\Context; +use Magento\Ui\Controller\Adminhtml\AbstractAction; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; + /** * Class Render - * - * @package Magento\Ui\Controller\Adminhtml\Index */ -class Render extends \Magento\Ui\Controller\Adminhtml\AbstractAction +class Render extends AbstractAction { + /** + * Constructor + * + * @param Context $context + * @param UiComponentFactory $factory + */ + public function __construct(Context $context, UiComponentFactory $factory) + { + parent::__construct($context, $factory); + } + /** * Action for AJAX request * @@ -20,8 +33,25 @@ class Render extends \Magento\Ui\Controller\Adminhtml\AbstractAction */ public function execute() { - $this->_response->appendBody( - $this->factory->createUiComponent($this->getComponent(), $this->getName())->render() - ); + $component = $this->factory->create($this->_request->getParam('namespace')); + $this->prepareComponent($component); + $this->_response->appendBody((string) $component->render()); + } + + /** + * Call prepare method in the component UI + * + * @param UiComponentInterface $component + * @return void + */ + protected function prepareComponent(UiComponentInterface $component) + { + $childComponents = $component->getChildComponents(); + if (!empty($childComponents)) { + foreach ($childComponents as $child) { + $this->prepareComponent($child); + } + } + $component->prepare(); } } diff --git a/app/code/Magento/Ui/Controller/UiActionInterface.php b/app/code/Magento/Ui/Controller/UiActionInterface.php index 33a13418955a5f5c351f0e8f6600da8acc2d2b00..53932aba49cce3a94a02175a622ab42aab57856e 100644 --- a/app/code/Magento/Ui/Controller/UiActionInterface.php +++ b/app/code/Magento/Ui/Controller/UiActionInterface.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,7 +7,6 @@ namespace Magento\Ui\Controller; /** * Interface UiActionInterface - * @package Magento\Ui\Controller */ interface UiActionInterface { diff --git a/app/code/Magento/Ui/DataProvider/Config/Converter.php b/app/code/Magento/Ui/DataProvider/Config/Converter.php deleted file mode 100644 index 6402821d585af92a6283787813f6e74fbdfcc860..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/Config/Converter.php +++ /dev/null @@ -1,248 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -namespace Magento\Ui\DataProvider\Config; - -use Magento\Framework\Config\ConverterInterface; - -/** - * Class Converter - */ -class Converter implements ConverterInterface -{ - /** - * @var \Magento\Eav\Model\Entity\TypeFactory - */ - protected $entityTypeFactory; - - /** - * Map EAV frontend_input property to form element types - * - * @var array - */ - protected $inputTypeMap = [ - 'text' => 'input', - 'textarea' => 'textarea', - 'multiline' => 'input', - 'date' => 'date', - 'select' => 'select', - 'multiselect' => 'multiselect', - 'boolean' => 'select', - 'file' => 'media', - 'image' => 'media', - ]; - - /** - * @param \Magento\Eav\Model\Entity\TypeFactory $entityTypeFactory - */ - public function __construct(\Magento\Eav\Model\Entity\TypeFactory $entityTypeFactory) - { - $this->entityTypeFactory = $entityTypeFactory; - } - - /** - * Transform Xml to array - * - * @param \DOMNode $source - * @return array - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function toArray(\DOMNode $source) - { - $result = []; - if ($source->hasAttributes()) { - foreach ($source->attributes as $attr) { - $result['@attributes'][$attr->name] = $attr->value; - } - } - - if (!$source->hasChildNodes()) { - if (empty($result)) { - $result = $source->nodeValue; - } - } else { - if ($source->hasChildNodes()) { - $groups = []; - foreach ($source->childNodes as $child) { - if ($child->nodeType == XML_TEXT_NODE || $child->nodeType == XML_COMMENT_NODE) { - continue; - } - if ($this->isTextNode($child)) { - $result[$child->nodeName] = $this->getTextNode($child)->data; - } else { - if (in_array($child->nodeName, ['validate', 'filter', 'readonly'])) { - if (!isset($result[$child->nodeName])) { - $result[$child->nodeName] = []; - } - $result[$child->nodeName][] = $this->toArray($child); - } else { - if (isset($result[$child->nodeName])) { - if (!isset($groups[$child->nodeName])) { - $result[$child->nodeName] = [$result[$child->nodeName]]; - $groups[$child->nodeName] = 1; - } - $result[$child->nodeName][] = $this->toArray($child); - } else { - $result[$child->nodeName] = $this->toArray($child); - } - } - } - } - } - } - return $result; - } - - /** - * Convert configuration - * - * @param \DOMDocument $source - * @return array - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function convert($source) - { - $data = []; - $output = $this->toArray($source); - foreach ($output['config']['dataSource'] as $dataSource) { - $data[$dataSource['@attributes']['name']] = [ - 'name' => $dataSource['@attributes']['name'], - 'label' => $dataSource['@attributes']['label'], - 'dataSet' => $dataSource['@attributes']['dataSet'], - ]; - $fields = []; - if (isset($dataSource['fields']['@attributes']['entityType'])) { - $entityType = $this->entityTypeFactory->create() - ->load($dataSource['fields']['@attributes']['entityType'], 'entity_type_code'); - $attributeCollection = $entityType->getAttributeCollection(); - foreach ($attributeCollection as $attribute) { - if ($attribute->getIsUserDefined()) { - $fields[$attribute->getAttributeCode()] = [ - 'name' => $attribute->getAttributeCode(), - 'source' => 'eav', - 'formElement' => $this->mapFrontendInput($attribute->getFrontendInput()), - 'is_required' => $attribute->getScopeIsRequired(), - 'default_value' => $attribute->getScopeDefaultValue(), - 'visible' => $attribute->getScopeIsVisible(), - 'multiline_count' => $attribute->getScopeMultilineCount(), - ]; - if ($attribute->getValidateRules()) { - $fields[$attribute->getAttributeCode()]['constraints']['validate'] - = $attribute->getValidateRules(); - } - } - } - } - foreach ($dataSource['fields']['field'] as $field) { - foreach ($field['@attributes'] as $key => $value) { - $fields[$field['@attributes']['name']][$key] = $value; - } - if (isset($field['@attributes']['source'])) { - if (in_array($field['@attributes']['source'], ['lookup', 'option', 'reference'])) { - $fields[$field['@attributes']['name']]['reference'] = [ - 'target' => $field['reference']['@attributes']['target'], - 'targetField' => $field['reference']['@attributes']['targetField'], - 'referencedField' => $field['reference']['@attributes']['referencedField'], - 'neededField' => $field['reference']['@attributes']['neededField'], - ]; - } - } - if (isset($field['tooltip'])) { - $fields[$field['@attributes']['name']]['tooltip'] = [ - 'link' => $field['tooltip']['link'], - 'description' => $field['tooltip']['description'], - ]; - } - if (isset($field['constraints']['validate'])) { - foreach ($field['constraints']['validate'] as $rule) { - $fields[$field['@attributes']['name']]['constraints']['validate'][$rule['@attributes']['name']] = - isset($rule['@attribute']['value']) - ? $rule['@attribute']['value'] : true; - } - } - if (isset($field['constraints']['filter'])) { - foreach ($field['constraints']['filter'] as $filter) { - $filterValues['on'] = isset($filter['@attributes']['on']) ? $filter['@attributes']['on'] : null; - $filterValues['by'] = isset($filter['@attributes']['by']) ? $filter['@attributes']['by'] : null; - $filterValues['value'] = isset($filter['@attributes']['value']) - ? $filter['@attributes']['value'] : null; - $fields[$field['@attributes']['name']]['constraints']['filter'][] = $filterValues; - } - } - if (isset($field['constraints']['readonly'])) { - foreach ($field['constraints']['readonly'] as $condition) { - $fields[$field['@attributes']['name']]['constraints']['readonly'][] = [ - 'on' => $condition['@attributes']['on'], - 'value' => $condition['@attributes']['value'], - ]; - } - } - } - $data[$dataSource['@attributes']['name']]['fields'] = $fields; - if (!empty($dataSource['references'])) { - foreach ($dataSource['references'] as $reference) { - $data[$reference['@attributes']['target']]['children'][$dataSource['@attributes']['name']][] = [ - 'targetField' => $reference['@attributes']['targetField'], - 'referencedField' => $reference['@attributes']['referencedField'], - ]; - } - } - } - - return $data; - } - - /** - * @param \DOMNode $node - * @return bool - */ - protected function isTextNode(\DOMNode $node) - { - $result = true; - if (!$node instanceof \DOMText) { - if ($node->hasChildNodes()) { - foreach ($node->childNodes as $child) { - if ($child->nodeType != XML_TEXT_NODE) { - $result = false; - break; - } - } - } else { - $result = false; - } - } - return $result; - } - - /** - * @param \DOMNode $node - * @return \DOMText - */ - protected function getTextNode(\DOMNode $node) - { - if ($node instanceof \DOMText) { - return $node; - } - foreach ($node->childNodes as $child) { - if ($child->nodeType == XML_TEXT_NODE) { - return $child; - } - } - return false; - } - - /** - * @param string $input - * @return string - */ - protected function mapFrontendInput($input) - { - return isset($this->inputTypeMap[$input]) ? $this->inputTypeMap[$input] : 'input'; - } -} diff --git a/app/code/Magento/Ui/DataProvider/Config/Data.php b/app/code/Magento/Ui/DataProvider/Config/Data.php deleted file mode 100644 index a975606507f0dcca2896847d54cf4a261eb09d01..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/Config/Data.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Ui\DataProvider\Config; - -/** - * Class Data - */ -class Data extends \Magento\Framework\Config\Data -{ - /** - * @param Reader $reader - * @param \Magento\Framework\Config\CacheInterface $cache - */ - public function __construct( - Reader $reader, - \Magento\Framework\Config\CacheInterface $cache - ) { - $this->cacheTags = [\Magento\Eav\Model\Entity\Attribute::CACHE_TAG]; - parent::__construct($reader, $cache, 'data_source'); - } - - /** - * @param string $name - * @return array|mixed|null - */ - public function getDataSource($name) - { - return $this->get($name); - } -} diff --git a/app/code/Magento/Ui/DataProvider/Config/FileResolver.php b/app/code/Magento/Ui/DataProvider/Config/FileResolver.php deleted file mode 100644 index fbd093b8c1acd0b47a2811897796da918a3ff14b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/Config/FileResolver.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Hierarchy config file resolver - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\DataProvider\Config; - -use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Config\FileIteratorFactory; -use Magento\Framework\Config\FileResolverInterface; -use Magento\Framework\Filesystem; - -/** - * Class FileResolver - */ -class FileResolver implements \Magento\Framework\Config\FileResolverInterface -{ - /** - * @var \Magento\Framework\Filesystem\Directory\ReadInterface - */ - protected $directoryRead; - - /** - * @var FileIteratorFactory - */ - protected $iteratorFactory; - - /** - * @param Filesystem $filesystem - * @param FileIteratorFactory $iteratorFactory - */ - public function __construct( - Filesystem $filesystem, - FileIteratorFactory $iteratorFactory - ) { - $this->directoryRead = $filesystem->getDirectoryRead(DirectoryList::MODULES); - $this->iteratorFactory = $iteratorFactory; - } - - /** - * {@inheritdoc} - */ - public function get($filename, $scope) - { - $iterator = $this->iteratorFactory->create( - $this->directoryRead, - $this->directoryRead->search('/*/*/etc/data_source/' . $filename) - ); - return $iterator; - } -} diff --git a/app/code/Magento/Ui/DataProvider/Config/Reader.php b/app/code/Magento/Ui/DataProvider/Config/Reader.php deleted file mode 100644 index 6360437f16eb38326cf8a69ec0f6bd8c24102da1..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/Config/Reader.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Ui\DataProvider\Config; - -use Magento\Framework\Config\ValidationStateInterface; - -/** - * Class Reader - */ -class Reader extends \Magento\Framework\Config\Reader\Filesystem -{ - /** - * List of id attributes for merge - * - * @var array - */ - protected $_idAttributes = ['/config/dataSource' => 'name']; - - /** - * @param FileResolver $fileResolver - * @param Converter $converter - * @param SchemaLocator $schemaLocator - * @param ValidationStateInterface $validationState - * @param string $fileName - * @param array $idAttributes - * @param string $domDocumentClass - * @param string $defaultScope - */ - public function __construct( - FileResolver $fileResolver, - Converter $converter, - SchemaLocator $schemaLocator, - ValidationStateInterface $validationState, - $fileName = '*.xml', - $idAttributes = [], - $domDocumentClass = 'Magento\Framework\Config\Dom', - $defaultScope = '' - ) { - parent::__construct( - $fileResolver, - $converter, - $schemaLocator, - $validationState, - $fileName, - $idAttributes, - $domDocumentClass, - $defaultScope - ); - } -} diff --git a/app/code/Magento/Ui/DataProvider/Config/SchemaLocator.php b/app/code/Magento/Ui/DataProvider/Config/SchemaLocator.php deleted file mode 100644 index 02f64378eefe18816c057dff8b19319ba49ec96a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/Config/SchemaLocator.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\DataProvider\Config; - -/** - * Class SchemaLocator - */ -class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface -{ - /** - * Path to corresponding XSD file with validation rules for both individual and merged configs - * - * @var string - */ - private $_schema; - - /** - * @param \Magento\Framework\Module\Dir\Reader $moduleReader - */ - public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader) - { - $this->_schema = $moduleReader->getModuleDir('etc', 'Magento_Ui') . '/data_source.xsd'; - } - - /** - * {@inheritdoc} - */ - public function getSchema() - { - return $this->_schema; - } - - /** - * {@inheritdoc} - */ - public function getPerFileSchema() - { - return $this->_schema; - } -} diff --git a/app/code/Magento/Ui/DataProvider/DataProviderCollectionInterface.php b/app/code/Magento/Ui/DataProvider/DataProviderCollectionInterface.php deleted file mode 100644 index b6cc0da7753b1fcd4e9b97558d22c31c19cc7f01..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/DataProviderCollectionInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\DataProvider; - -use Magento\Framework\View\Element\UiComponent\DataProviderInterface; - -/** - * Interface DataProviderCollectionInterface - */ -interface DataProviderCollectionInterface extends DataProviderInterface -{ - /** - * Add a filter to the data - * - * @param array $filter - * @return void - */ - public function addFilter(array $filter); - - /** - * Get data - * - * @return \Magento\Framework\Object[] - */ - public function getData(); -} diff --git a/app/code/Magento/Ui/DataProvider/DataProviderEntityInterface.php b/app/code/Magento/Ui/DataProvider/DataProviderEntityInterface.php deleted file mode 100644 index f36e72f9f2eb7dac08f6556bd9e4f2541a905ef4..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/DataProviderEntityInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\DataProvider; - -use Magento\Framework\View\Element\UiComponent\DataProviderInterface; - -/** - * Interface DataProviderEntityInterface - */ -interface DataProviderEntityInterface extends DataProviderInterface -{ - const CONFIG_KEY = 'field'; -} diff --git a/app/code/Magento/Ui/DataProvider/EavValidationRul.php b/app/code/Magento/Ui/DataProvider/EavValidationRul.php new file mode 100644 index 0000000000000000000000000000000000000000..1d338ec30755af34f8653ca99b65f8202b141d7a --- /dev/null +++ b/app/code/Magento/Ui/DataProvider/EavValidationRul.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\DataProvider; + +use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; + +/** + * Class EavValidationRul + */ +class EavValidationRul +{ + /** + * @var array + */ + protected $validationRul = [ + 'input_validation' => [ + 'email' => ['validate-email' => true], + 'date' => ['validate-date' => true], + ], + ]; + + /** + * Build validation rules + * + * @param AbstractAttribute $attribute + * @param array $data + * @return array + */ + public function build(AbstractAttribute $attribute, array $data) + { + $rules = []; + if (isset($data['required']) && $data['required'] == 1) { + $rules['required-entry'] = true; + } + $validation = $attribute->getValidateRules(); + if (!empty($validation)) { + foreach ($validation as $type => $ruleName) { + switch ($type) { + case 'input_validation': + if (isset($this->validationRul[$type][$ruleName])) { + $rules = array_merge($rules, $this->validationRul[$type][$ruleName]); + } + break; + case 'min_text_length': + case 'max_text_length': + $rules = array_merge($rules, [$type => $ruleName]); + break; + } + + } + } + + return $rules; + } +} diff --git a/app/code/Magento/Ui/DataProvider/Manager.php b/app/code/Magento/Ui/DataProvider/Manager.php deleted file mode 100644 index c2f2379ff77ba8ded751261fe6754a1c1241067c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/Manager.php +++ /dev/null @@ -1,153 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Ui\DataProvider; - -use Magento\Framework\ObjectManagerInterface; -use Magento\Ui\DataProvider\Config\Data as Config; - -/** - * Class Manager - */ -class Manager -{ - /** - * @var Config - */ - protected $config; - - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * @var ObjectManagerInterface - */ - protected $metadataFactory; - - /** - * @var array - */ - protected $cache = []; - - /** - * @param Config $config - * @param ObjectManagerInterface $objectManager - * @param MetadataFactory $metadataFactory - */ - public function __construct(Config $config, ObjectManagerInterface $objectManager, MetadataFactory $metadataFactory) - { - $this->config = $config; - $this->objectManager = $objectManager; - $this->metadataFactory = $metadataFactory; - } - - /** - * Returns Data Source metadata - * - * @param string $dataSource - * @return \Magento\Ui\DataProvider\Metadata - */ - public function getMetadata($dataSource) - { - return $this->metadataFactory->create( - [ - 'config' => $this->config->getDataSource($dataSource), - ] - ); - } - - /** - * @param string $dataSource - * @param array $filters - * @return mixed - */ - public function getCollectionData($dataSource, array $filters = []) - { - $collectionHash = md5($dataSource . serialize($filters)); - if (!isset($this->cache[$collectionHash])) { - $config = $this->config->getDataSource($dataSource); - /** @var \Magento\Framework\Data\Collection\Db $collection */ - $collection = $this->objectManager->create($config['dataSet']); - - foreach ($config['fields'] as $field) { - if (isset($field['source']) && $field['source'] == 'eav') { - $collection->addAttributeToSelect($field['name']); - } - } - - if ($filters) { - foreach ($filters as $field => $expression) { - $collection->addFieldToFilter($field, $expression); - } - } - $this->cache[$collectionHash] = $collection->getItems(); - } - return $this->cache[$collectionHash]; - } - - /** - * Returns data by specified Data Source name - * - * @param string $dataSource - * @param array $filters - * @return array - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function getData($dataSource, array $filters = []) - { - $children = $this->getMetadata($dataSource)->getChildren(); - $fields = $this->getMetadata($dataSource)->getFields(); - $items = $this->getCollectionData($dataSource, $filters); - - $rows = []; - foreach ($items as $item) { - $row = []; - foreach ($fields as $name => $field) { - if (isset($field['source']) && $field['source'] == 'lookup') { - $lookupCollection = $this->getCollectionData( - $field['reference']['target'], - [$field['reference']['targetField'] => $item->getData($field['reference']['referencedField'])] - ); - $lookup = reset($lookupCollection); - $row[$name] = $lookup[$field['reference']['neededField']]; - } elseif (isset($field['source']) && $field['source'] == 'reference') { - $lookupCollection = $this->getCollectionData( - $field['reference']['target'], - [$field['reference']['targetField'] => $item->getData($field['reference']['referencedField'])] - ); - $lookup = reset($lookupCollection); - $isReferenced = isset($lookup[$field['reference']['neededField']]) - && $lookup[$field['reference']['neededField']] == $item->getId(); - $row[$name] = $isReferenced; - } elseif (isset($field['source']) && $field['source'] == 'option') { - $row[$name] = $item->getData($field['reference']['referencedField']); - } else { - $row[$name] = $item->getData($name); - } - - if (isset($field['size'])) { - $row[$name] = explode("\n", $row[$name]); - } - } - if (!empty($children)) { - foreach ($children as $name => $reference) { - $filter = []; - foreach ($reference as $metadata) { - $filter[$metadata['referencedField']] = $row[$metadata['targetField']]; - } - $row[$name] = $this->getData($name, $filter); - if (empty($row[$name])) { - unset($row[$name]); - } - } - } - $rows[$item->getId()] = $row; - } - return $rows; - } -} diff --git a/app/code/Magento/Ui/DataProvider/Metadata.php b/app/code/Magento/Ui/DataProvider/Metadata.php deleted file mode 100644 index 0d86e46754b76349a63947d928f43f1cf44b7261..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/DataProvider/Metadata.php +++ /dev/null @@ -1,324 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Ui\DataProvider; - -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\Validator\UniversalFactory; - -/** - * Class Metadata - */ -class Metadata implements \Iterator, \ArrayAccess -{ - /** - * Node name of children data sources - */ - const CHILD_DATA_SOURCES = 'childDataSources'; - - /** - * @var array - */ - protected $config; - - /** - * @var array - */ - protected $metadata = []; - - /** - * @var array - */ - protected $attributes = []; - - /** - * @var \Magento\Eav\Model\Entity\Collection\AbstractCollection - */ - protected $dataSet; - - /** - * @var array - */ - protected $children; - - /** - * @var Manager - */ - protected $manager; - - /** - * @var UniversalFactory - */ - protected $universalFactory; - - /** - * @param ObjectManagerInterface $objectManager - * @param Manager $manager - * @param UniversalFactory $universalFactory - * @param array $config - */ - public function __construct( - ObjectManagerInterface $objectManager, - Manager $manager, - UniversalFactory $universalFactory, - array $config - ) { - $this->config = $config; - if (isset($this->config['children'])) { - $this->config['fields'][self::CHILD_DATA_SOURCES] = $config['children']; - } - $this->dataSet = $objectManager->get($this->config['dataSet']); - $this->manager = $manager; - $this->universalFactory = $universalFactory; - $this->initAttributes(); - - foreach ($this->config['fields'] as $name => & $field) { - $this->prepare($name, $field); - } - } - - /** - * Return Data Source fields - * - * @return array - */ - public function getFields() - { - return isset($this->config['fields']) ? $this->config['fields'] : []; - } - - /** - * Return Data Source children - * - * @return array - */ - public function getChildren() - { - return isset($this->config['children']) ? $this->config['children'] : []; - } - - /** - * Return Data Source label - * - * @return string - */ - public function getLabel() - { - return $this->config['label']; - } - - /** - * Reset the Collection to the first element - * - * @return mixed - */ - public function rewind() - { - return reset($this->config['fields']); - } - - /** - * Return the current element - * - * @return mixed - */ - public function current() - { - return current($this->config['fields']); - } - - /** - * Return the key of the current element - * - * @return string - */ - public function key() - { - return key($this->config['fields']); - } - - /** - * Move forward to next element - * - * @return mixed - */ - public function next() - { - return next($this->config['fields']); - } - - /** - * Checks if current position is valid - * - * @return bool - */ - public function valid() - { - return (bool)$this->key(); - } - - /** - * Returns price class by code - * - * @param string $code - * @return string|array - */ - public function get($code) - { - return isset($this->config['fields'][$code]) ? $this->config['fields'][$code] : false; - } - - /** - * The value to set. - * - * @param string $offset - * @param string $value - * @return void - */ - public function offsetSet($offset, $value) - { - if ($offset === null) { - $this->config['fields'][] = $value; - } else { - $this->config['fields'][$offset] = $value; - } - } - - /** - * The return value will be casted to boolean if non-boolean was returned. - * - * @param string $offset - * @return bool - */ - public function offsetExists($offset) - { - return isset($this->config['fields'][$offset]); - } - - /** - * The offset to unset. - * - * @param string $offset - * @return void - */ - public function offsetUnset($offset) - { - unset($this->config['fields'][$offset]); - } - - /** - * The offset to retrieve. - * - * @param string $offset - * @return string - */ - public function offsetGet($offset) - { - return isset($this->config['fields'][$offset]) ? $this->config['fields'][$offset] : null; - } - - /** - * @return void - */ - protected function initAttributes() - { - if (empty($this->attributes)) { - foreach ($this->config['fields'] as $field) { - if (isset($field['source']) && $field['source'] == 'eav') { - $attribute = $this->dataSet->getEntity()->getAttribute($field['name']); - if ($attribute) { - $this->attributes[$field['name']] = $attribute->getData(); - $options = []; - if ($attribute->usesSource()) { - $options = $attribute->getSource()->getAllOptions(); - } - $this->attributes[$field['name']]['options'] = $options; - $this->attributes[$field['name']]['is_required'] = $attribute->getIsRequired(); - } - } - } - } - } - - /** - * @param string $name - * @param array $field - * @return void - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - protected function prepare($name, array & $field) - { - if ($name == self::CHILD_DATA_SOURCES) { - foreach ($field as $childName => $childConfig) { - $field[$childName] = $this->manager->getMetadata($childName); - } - return; - } - - $options = []; - if (isset($field['source'])) { - if ($field['source'] == 'option') { - $rawOptions = $this->manager->getData( - $field['reference']['target'] - ); - $options[] = [ - 'label' => __('Please, select...'), - 'value' => null, - ]; - foreach ($rawOptions as $rawOption) { - $options[] = [ - 'label' => $rawOption[$field['reference']['neededField']], - 'value' => $rawOption[$field['reference']['targetField']], - - ]; - } - } - } else { - if (isset($field['optionProvider'])) { - list($source, $method) = explode('::', $field['optionProvider']); - $sourceModel = $this->universalFactory->create($source); - $options = $sourceModel->$method(); - } - } - - $attributeCodes = [ - 'options' => ['eav_map' => 'options', 'default' => $options], - 'dataType' => ['eav_map' => 'frontend_input', 'default' => 'text'], - 'filterType' => ['default' => 'input_filter'], - 'formElement' => ['default' => 'input'], - 'displayArea' => ['default' => 'body'], - 'visible' => ['eav_map' => 'is_visible', 'default' => true], - 'required' => ['eav_map' => 'is_required', 'default' => false], - 'label' => ['eav_map' => 'frontend_label'], - 'sortOrder' => ['eav_map' => 'sort_order'], - 'notice' => ['eav_map' => 'note'], - 'default' => ['eav_map' => 'default_value'], - 'unique' => [], - 'description' => [], - 'constraints' => [], - 'customEntry' => [], - 'size' => ['eav_map' => 'scope_multiline_count'], - 'tooltip' => [], - 'fieldGroup' => [], - ]; - - foreach ($attributeCodes as $code => $info) { - if (!isset($field[$code])) { - if (isset($this->attributes[$name]) && isset($info['eav_map'])) { - $field[$code] = $this->attributes[$name][$info['eav_map']]; - } elseif (empty($field[$code]) && !empty($info['default'])) { - $field[$code] = $info['default']; - } - } - } - - if (isset($field['required']) && $field['required']) { - $field['constraints']['validate']['required-entry'] = true; - } - } -} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml.php b/app/code/Magento/Ui/TemplateEngine/Xhtml.php new file mode 100644 index 0000000000000000000000000000000000000000..e4a7765e90f79c0e2ad0223177707d0ed528c18c --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine; + +use Magento\Ui\TemplateEngine\Xhtml\Result; +use Magento\Ui\TemplateEngine\Xhtml\Template; +use Magento\Ui\TemplateEngine\Xhtml\Compiler; +use Magento\Ui\TemplateEngine\Xhtml\ResultFactory; +use Magento\Framework\View\Element\BlockInterface; +use Magento\Framework\View\TemplateEngineInterface; +use Magento\Ui\TemplateEngine\Xhtml\CompilerFactory; +use Magento\Ui\TemplateEngine\Xhtml\TemplateFactory; +use Magento\Framework\View\Element\UiComponent\Config\Provider\Template as TemplateProvider; + +/** + * Class Xhtml + */ +class Xhtml implements TemplateEngineInterface +{ + const INSTANCE_NAME = 'Magento\Ui\Content\Template\Type\Xhtml\Template'; + + /** + * @var TemplateProvider + */ + protected $templateProvider; + + /** + * @var ResultFactory + */ + protected $resultFactory; + + /** + * @var TemplateFactory + */ + protected $templateFactory; + + /** + * @var CompilerFactory + */ + protected $compilerFactory; + + /** + * Constructor + * + * @param TemplateProvider $templateProvider + * @param ResultFactory $resultFactory + * @param TemplateFactory $templateFactory + * @param CompilerFactory $compilerFactory + */ + public function __construct( + TemplateProvider $templateProvider, + ResultFactory $resultFactory, + TemplateFactory $templateFactory, + CompilerFactory $compilerFactory + ) { + $this->templateProvider = $templateProvider; + $this->resultFactory = $resultFactory; + $this->templateFactory = $templateFactory; + $this->compilerFactory = $compilerFactory; + } + + /** + * Render template + * + * Render the named template in the context of a particular block and with + * the data provided in $vars. + * + * @param \Magento\Framework\View\Element\BlockInterface $block + * @param string $templateFile + * @param array $dictionary + * @return Result + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function render(BlockInterface $block, $templateFile, array $dictionary = []) + { + /** @var Template $template */ + $template = $this->templateFactory->create(['content' => $this->templateProvider->getTemplate($templateFile)]); + + /** @var Result $result */ + $result = $this->resultFactory->create( + [ + 'template' => $template, + 'compiler' => $this->compilerFactory->create(), + 'component' => $block + ] + ); + + return $result; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php new file mode 100644 index 0000000000000000000000000000000000000000..68830d2a6574ffa1cd1bc82579cff98f56ea7a90 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php @@ -0,0 +1,175 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml; + +use Magento\Framework\Object; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\TemplateEngine\Xhtml\Compiler\TextInterface; +use Magento\Ui\TemplateEngine\Xhtml\Compiler\CdataInterface; +use Magento\Ui\TemplateEngine\Xhtml\Compiler\CommentInterface; +use Magento\Ui\TemplateEngine\Xhtml\Compiler\AttributeInterface; +use Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\ElementInterface; + +/** + * Class Compiler + */ +class Compiler +{ + const PATTERN_TAG = '|@|'; + + /** + * @var TextInterface + */ + protected $compilerText; + + /** + * @var AttributeInterface + */ + protected $compilerAttribute; + + /** + * @var CdataInterface + */ + protected $compilerCdata; + + /** + * @var CommentInterface + */ + protected $compilerComment; + + /** + * @var ElementInterface[] + */ + protected $elementCompilers; + + /** + * Postprocessing data + * + * @var array + */ + protected $data; + + /** + * Constructor + * + * @param TextInterface $compilerText + * @param AttributeInterface $compilerAttribute + * @param AttributeInterface|CdataInterface $compilerCdata + * @param CommentInterface $compilerComment + * @param ElementInterface[] $elementCompilers + */ + public function __construct( + TextInterface $compilerText, + AttributeInterface $compilerAttribute, + CdataInterface $compilerCdata, + CommentInterface $compilerComment, + array $elementCompilers + ) { + $this->compilerText = $compilerText; + $this->compilerAttribute = $compilerAttribute; + $this->compilerCdata = $compilerCdata; + $this->compilerComment = $compilerComment; + $this->elementCompilers = $elementCompilers; + } + + /** + * The compilation of the template and filling in the data + * + * @param \DOMNode $node + * @param UiComponentInterface $component + * @param Object $context + * @return void + */ + public function compile(\DOMNode $node, UiComponentInterface $component, Object $context) + { + switch ($node->nodeType) { + case XML_TEXT_NODE: + $this->compilerText->compile($node, $component); + break; + case XML_CDATA_SECTION_NODE: + $this->compilerCdata->compile($node, $component); + break; + case XML_COMMENT_NODE: + $this->compilerComment->compile($node, $component); + break; + default: + /** @var \DomElement $node */ + if ($node->hasAttributes()) { + foreach ($node->attributes as $attribute) { + $this->compilerAttribute->compile($attribute, $component); + } + } + $compiler = $this->getElementCompiler($node->nodeName); + if (null !== $compiler) { + $compiler->compile($this, $node, $component, $context); + } else if ($node->hasChildNodes()) { + foreach ($this->getChildNodes($node) as $child) { + $this->compile($child, $component, $context); + } + } + } + } + + /** + * Run postprocessing contents template + * + * @param string $content + * @return string + */ + public function postprocessing($content) + { + return preg_replace_callback( + '#' . preg_quote(static::PATTERN_TAG) . '(.+?)' . preg_quote(static::PATTERN_TAG) . '#', + function ($match) { + return isset($this->data[$match[1]]) ? $this->data[$match[1]] : ''; + }, + $content + ); + } + + /** + * Set postprocessing data + * + * @param string $key + * @param string $content + * @return void + */ + public function setPostprocessingData($key, $content) + { + $this->data[$key] = $content; + } + + /** + * Get child nodes + * + * @param \DOMElement $node + * @return \DOMElement[] + */ + protected function getChildNodes(\DOMElement $node) + { + $childNodes = []; + foreach ($node->childNodes as $child) { + $childNodes[] = $child; + } + + return $childNodes; + } + + /** + * Get element compiler by name + * + * @param string $name + * @return ElementInterface + */ + protected function getElementCompiler($name) + { + if (isset($this->elementCompilers[$name])) { + return $this->elementCompilers[$name]; + } + + return null; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php new file mode 100644 index 0000000000000000000000000000000000000000..f1ab640960831615310268cc4d99e6dc39fcd415 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\DirectiveInterface; + +/** + * Class Attribute + */ +class Attribute implements AttributeInterface +{ + /** + * @var DirectiveInterface[] + */ + protected $directivePool; + + /** + * Constructor + * + * @param DirectiveInterface[] $directivePool + */ + public function __construct(array $directivePool) + { + $this->directivePool = $directivePool; + } + + /** + * Compiles the Element node + * + * @param \DOMAttr $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMAttr $node, UiComponentInterface $component) + { + foreach ($this->directivePool as $directive) { + $node->value = preg_replace_callback( + $directive->getPattern(), + function ($match) use ($directive, $component) { + return $directive->execute($match, $component); + }, + $node->value + ); + } + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..274d43bcde56dd2f793d0b5a2fd01abae047c9f6 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface AttributeInterface + */ +interface AttributeInterface +{ + /** + * Compiles the Element node + * + * @param \DOMAttr $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMAttr $node, UiComponentInterface $component); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Cdata.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Cdata.php new file mode 100644 index 0000000000000000000000000000000000000000..785a86eb5c2b36a46691383b702b7dd1c39a556b --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Cdata.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Cdata + */ +class Cdata implements CdataInterface +{ + /** + * Compiles the CData Section node + * + * @param \DOMCdataSection $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMCdataSection $node, UiComponentInterface $component) + { + // + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CdataInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CdataInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d37d9460fc2f8a49cbef9689a53776918e3fa2d4 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CdataInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface CdataInterface + */ +interface CdataInterface +{ + /** + * Compiles the CData Section node + * + * @param \DOMCdataSection $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMCdataSection $node, UiComponentInterface $component); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Comment.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Comment.php new file mode 100644 index 0000000000000000000000000000000000000000..2ad634611ab74b0d762947a1ac54b8695bd37768 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Comment.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Comment + */ +class Comment implements CommentInterface +{ + /** + * Compiles the Comment node + * + * @param \DOMComment $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMComment $node, UiComponentInterface $component) + { + // + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CommentInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CommentInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..19a2d6569c977a056e22cd69322475616f736acb --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CommentInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface CommentInterface + */ +interface CommentInterface +{ + /** + * Compiles the Comment node + * + * @param \DOMComment $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMComment $node, UiComponentInterface $component); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php new file mode 100644 index 0000000000000000000000000000000000000000..ef14461f3610f8b3fc914a646b58ba62a73f2122 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class CallableMethod + */ +class CallableMethod implements DirectiveInterface +{ + /** + * Execute directive + * + * @param array $directive + * @param UiComponentInterface $component + * @return string + */ + public function execute($directive, UiComponentInterface $component) + { + $object = $component; + $result = ''; + foreach (explode('.', $directive[1]) as $method) { + $methodName = substr($method, 0, strpos($method, '(')); + if (is_callable([$object, $methodName])) { + $result = $object->$methodName(); + if (is_scalar($result)) { + break; + } + $object = $result; + continue; + } + break; + } + + return $result; + } + + /** + * Get regexp search pattern + * + * @return string + */ + public function getPattern() + { + return '#\{\{((?:[\w_0-9]+\(\)){1}(?:(?:\.[\w_0-9]+\(\))+)?)\}\}#'; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b367a6b84f7b3edb47869b967a88e66dd84a6cf1 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface DirectiveInterface + */ +interface DirectiveInterface +{ + /** + * Execute directive + * + * @param array $directive + * @param UiComponentInterface $component + * @return string + */ + public function execute($directive, UiComponentInterface $component); + + /** + * Get regexp search pattern + * + * @return string + */ + public function getPattern(); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/Variable.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/Variable.php new file mode 100644 index 0000000000000000000000000000000000000000..b903855c821912ed3ec9d19eb1feb575c0e8c017 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/Variable.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Variable + */ +class Variable implements DirectiveInterface +{ + /** + * Execute directive + * + * @param array $directive + * @param UiComponentInterface $component + * @return string + */ + public function execute($directive, UiComponentInterface $component) + { + return $component->getData($directive[1]); + } + + /** + * Get regexp search pattern + * + * @return string + */ + public function getPattern() + { + return '#\{\{([^\}\(]+)\}\}#'; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php new file mode 100644 index 0000000000000000000000000000000000000000..1b31288c66fd8d397a64a2ee9e766fa6008856f1 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; + +use Magento\Framework\Object; +use Magento\Ui\TemplateEngine\Xhtml\Compiler; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Content + */ +class Content implements ElementInterface +{ + /** + * Compiles the Element node + * + * @param Compiler $compiler + * @param \DOMElement $node + * @param UiComponentInterface $component + * @param Object $context + * @return void + */ + public function compile( + Compiler $compiler, + \DOMElement $node, + UiComponentInterface $component, + Object $context + ) { + $name = $node->getAttribute('name'); + $content = (string)$component->renderChildComponent($name); + $name .= '_' . sprintf('%x', crc32(spl_object_hash($context))); + if (!empty($content)) { + $compiler->setPostprocessingData($name, $content); + $newNode = $node->ownerDocument->createTextNode( + Compiler::PATTERN_TAG . $name . Compiler::PATTERN_TAG + ); + $node->parentNode->replaceChild($newNode, $node); + } else { + $node->parentNode->removeChild($node); + } + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..9ce4c9f74583636d568a83ac45456ecdffb8222c --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; + +use Magento\Framework\Object; +use Magento\Ui\TemplateEngine\Xhtml\Compiler; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface ElementInterface + */ +interface ElementInterface +{ + /** + * Compiles the Element node + * + * @param Compiler $compiler + * @param \DOMElement $node + * @param UiComponentInterface $component + * @param Object $context + * @return void + */ + public function compile( + Compiler $compiler, + \DOMElement $node, + UiComponentInterface $component, + Object $context + ); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php new file mode 100644 index 0000000000000000000000000000000000000000..513be2d1daf676ed9c433c82a2f23cbce0f3d588 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; + +use Magento\Framework\Object; +use Magento\Ui\TemplateEngine\Xhtml\Compiler; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Form + */ +class Form implements ElementInterface +{ + /** + * Compiles the Element node + * + * @param Compiler $compiler + * @param \DOMElement $node + * @param UiComponentInterface $component + * @param Object $context + * @return void + */ + public function compile( + Compiler $compiler, + \DOMElement $node, + UiComponentInterface $component, + Object $context + ) { + foreach ($this->getChildNodes($node) as $child) { + $compiler->compile($child, $component, $context); + } + } + + /** + * Get child nodes + * + * @param \DOMElement $node + * @return \DOMElement[] + */ + protected function getChildNodes(\DOMElement $node) + { + $childNodes = []; + foreach ($node->childNodes as $child) { + $childNodes[] = $child; + } + + return $childNodes; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php new file mode 100644 index 0000000000000000000000000000000000000000..9118a5e6b6aef4cd9a00cea1e21ec38234334660 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; + +use Magento\Framework\Object; +use Magento\Ui\TemplateEngine\Xhtml\Compiler; +use Magento\Ui\TemplateEngine\Xhtml\Result; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Render + */ +class Render implements ElementInterface +{ + /** + * Compiles the Element node + * + * @param Compiler $compiler + * @param \DOMElement $node + * @param UiComponentInterface $component + * @param Object $context + * @return void + */ + public function compile( + Compiler $compiler, + \DOMElement $node, + UiComponentInterface $component, + Object $context + ) { + $result = $component->renderChildComponent($node->getAttribute('name')); + if ($result instanceof Result) { + $node->parentNode->replaceChild($result->getDocumentElement(), $node); + } else if (!empty($result) && is_scalar($result)) { + $newFragment = $node->ownerDocument->createDocumentFragment(); + $newFragment->appendXML($result); + $node->parentNode->replaceChild($newFragment, $node); + $node->parentNode->removeChild($node); + } else { + $node->parentNode->removeChild($node); + } + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php new file mode 100644 index 0000000000000000000000000000000000000000..5bdfe50622c2a5b13000b10e9848265fc46e847f --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\DirectiveInterface; + +/** + * Class Text + */ +class Text implements TextInterface +{ + /** + * @var DirectiveInterface[] + */ + protected $directivePool; + + /** + * Constructor + * + * @param DirectiveInterface[] $directivePool + */ + public function __construct(array $directivePool) + { + $this->directivePool = $directivePool; + } + + /** + * Compiles the Element node + * + * @param \DOMText $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMText $node, UiComponentInterface $component) + { + $result = ''; + foreach ($this->directivePool as $directive) { + $result = preg_replace_callback( + $directive->getPattern(), + function ($match) use ($directive, $component) { + return $directive->execute($match, $component); + }, + $node->textContent + ); + } + + $newNode = $node->ownerDocument->createTextNode($result); + $node->parentNode->replaceChild($newNode, $node); + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..1f1ffc41586164cbf0da8b960007b0c27c998476 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface TextInterface + */ +interface TextInterface +{ + /** + * Compiles the Element node + * + * @param \DOMText $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMText $node, UiComponentInterface $component); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php new file mode 100644 index 0000000000000000000000000000000000000000..2ad357022989fe9d7a4c9bd04d71d0faef71e151 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml; + +use Magento\Ui\Component\Layout\Generator\Structure; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Result + */ +class Result +{ + /** + * @var Template + */ + protected $template; + + /** + * @var Compiler + */ + protected $compiler; + + /** + * @var UiComponentInterface + */ + protected $component; + + /** + * @var Structure + */ + protected $structure; + + /** + * Constructor + * + * @param Template $template + * @param Compiler $compiler + * @param UiComponentInterface $component + * @param Structure $structure + */ + public function __construct( + Template $template, + Compiler $compiler, + UiComponentInterface $component, + Structure $structure + ) { + $this->template = $template; + $this->compiler = $compiler; + $this->component = $component; + $this->structure = $structure; + } + + /** + * Get result document root element \DOMElement + * + * @return \DOMElement + */ + public function getDocumentElement() + { + return $this->template->getDocumentElement(); + } + + /** + * Append layout configuration + * + * @return void + */ + public function appendLayoutConfiguration() + { + $layoutConfiguration = $this->wrapContent(json_encode($this->structure->generate($this->component))); + $this->template->append($layoutConfiguration); + } + + /** + * Returns the string representation + * + * @return string + */ + public function __toString() + { + try { + $templateRootElement = $this->getDocumentElement(); + foreach ($templateRootElement->attributes as $name => $attribute) { + if ('noNamespaceSchemaLocation' === $name) { + $this->getDocumentElement()->removeAttributeNode($attribute); + break; + } + } + $templateRootElement->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi'); + $this->compiler->compile($templateRootElement, $this->component, $this->component); + $this->appendLayoutConfiguration(); + $result = $this->compiler->postprocessing($this->template->__toString()); + } catch (\Exception $e) { + $result = ''; + } + return $result; + } + + /** + * Wrap content + * + * @param string $content + * @return string + */ + protected function wrapContent($content) + { + return '<script type="text/x-magento-init"><![CDATA[' + . '{"*": {"Magento_Ui/js/core/app": ' . str_replace(['<![CDATA[', ']]>'], '', $content) . '}}' + . ']]></script>'; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php new file mode 100644 index 0000000000000000000000000000000000000000..52cc35f0cf461c943598ba3206fdebe6ea26b824 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\TemplateEngine\Xhtml; + +/** + * Class Template + */ +class Template +{ + const XML_VERSION = '1.0'; + + const XML_ENCODING = 'UTF-8'; + + /** + * @var \DOMElement + */ + protected $templateNode; + + /** + * Constructor + * + * @param string $content + */ + public function __construct($content) + { + $document = new \DOMDocument(static::XML_VERSION, static::XML_ENCODING); + $document->loadXML($content); + $this->templateNode = $document->documentElement; + } + + /** + * Get template root element + * + * @return \DOMElement + */ + public function getDocumentElement() + { + return $this->templateNode; + } + + /** + * Append + * + * @param string $content + * @return void + */ + public function append($content) + { + $newFragment = $this->templateNode->ownerDocument->createDocumentFragment(); + $newFragment->appendXML($content); + $this->templateNode->appendChild($newFragment); + } + + /** + * Returns the string representation + * + * @return string + */ + public function __toString() + { + try { + $this->templateNode->ownerDocument->normalizeDocument(); + $result = $this->templateNode->ownerDocument->saveHTML(); + } catch (\Exception $e) { + $result = ''; + } + return $result; + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php b/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php index 461515aafe6c82463b6cde76ca5823502422b171..eaae007216af0aa226ff98336e22c727190102a0 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php @@ -127,18 +127,20 @@ class ActionPoolTest extends \PHPUnit_Framework_TestCase ->method('setChild') ->with($this->key, $toolbarContainerMock) ->willReturnSelf(); - $this->assertNull($this->actionPool->add($this->key, $data, $this->uiComponentInterfaceMock)); + $this->actionPool->add($this->key, $data, $this->uiComponentInterfaceMock); } public function testRemove() { - $this->assertNull($this->actionPool->remove($this->key)); + $this->testAdd(); + $this->actionPool->remove($this->key); } public function testUpdate() { + $this->testAdd(); $data = ['id' => 'id']; $this->items[$this->key]->expects($this->any())->method('setData')->with($data)->willReturnSelf(); - $this->assertNull($this->actionPool->update($this->key, $data)); + $this->actionPool->update($this->key, $data); } } diff --git a/app/code/Magento/Ui/Test/Unit/Component/Control/ActionTest.php b/app/code/Magento/Ui/Test/Unit/Component/Control/ActionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..be25a5957f10d22e90fc5f2b91be11910b60b342 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/Control/ActionTest.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Test\Unit\Component\Control; + +use Magento\Ui\Component\Control\Action; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +/** + * Class ActionTest + */ +class ActionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Action + */ + protected $action; + + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * Set up + */ + public function setUp() + { + $this->objectManager = new ObjectManager($this); + + $this->action = $this->objectManager->getObject('Magento\Ui\Component\Control\Action'); + } + + /** + * Run test getComponentName method + * + * @return void + */ + public function testGetComponentName() + { + $this->assertTrue($this->action->getComponentName() === Action::NAME); + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/Control/ButtonTest.php b/app/code/Magento/Ui/Test/Unit/Component/Control/ButtonTest.php index 998e677f7e9df92ebdf92df4ae708fa8346e80ae..84284dea69d092dc4b6553734067a846412f83b2 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Control/ButtonTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/Control/ButtonTest.php @@ -59,7 +59,7 @@ class ButtonTest extends \PHPUnit_Framework_TestCase public function testGetAttributesHtml() { $expected = 'type="button" class="action- scalable classValue disabled" ' - . 'onclick="setLocation(\'url2\');" disabled="disabled" data-attributeKey="attributeValue" '; + . 'onclick="location.href = \'url2\';" disabled="disabled" data-attributeKey="attributeValue" '; $this->button->setDisabled(true); $this->button->setData('url', 'url2'); $this->button->setData('class', 'classValue'); @@ -98,12 +98,12 @@ class ButtonTest extends \PHPUnit_Framework_TestCase { return [ [null, null, '', null], - [null, null, 'get_url', 'setLocation(\'get_url\');'], + [null, null, 'get_url', 'location.href = \'get_url\';'], ['on_click', null, null, 'on_click'], ['on_click', 'url', 'get_url', 'on_click'], ['on_click', null, '', 'on_click'], - [null, 'url', 'get_url', 'setLocation(\'url\');'], - [null, 'url', '', 'setLocation(\'url\');'], + [null, 'url', 'get_url', 'location.href = \'url\';'], + [null, 'url', '', 'location.href = \'url\';'], ]; } } diff --git a/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php b/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php index 72b28b39c7f42637fa77d4d0ffb2b3a194c637bd..9251da5b69dffd7adee6d34dd9fff76c7babe17a 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php @@ -17,7 +17,7 @@ class ContainerTest extends \PHPUnit_Framework_TestCase $blockName = $nameInLayout . '-' . $id . '-button'; $expectedHtml = 'test html'; - $blockButtonMock = $this->getMock(Container::DEFAULT_BUTTON, [], [], '', false); + $blockButtonMock = $this->getMock(Container::DEFAULT_CONTROL, [], [], '', false); $blockButtonMock->expects($this->once())->method('toHtml')->willReturn($expectedHtml); $contextMock = $this->getMock('Magento\Framework\View\Element\Template\Context', [], [], '', false); @@ -32,7 +32,7 @@ class ContainerTest extends \PHPUnit_Framework_TestCase $layoutMock = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); $layoutMock->expects($this->once()) ->method('createBlock') - ->with(Container::DEFAULT_BUTTON, $blockName) + ->with(Container::DEFAULT_CONTROL, $blockName) ->willReturn($blockButtonMock); $contextMock->expects($this->any())->method('getLayout')->willReturn($layoutMock); diff --git a/app/code/Magento/Ui/Test/Unit/Component/Control/LinkTest.php b/app/code/Magento/Ui/Test/Unit/Component/Control/LinkTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1615690f8674f3668f502e6b45328c535286fe74 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/Control/LinkTest.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Test\Unit\Component\Control; + +use Magento\Ui\Component\Control\Link; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +/** + * Class LinkTest + */ +class LinkTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Link + */ + protected $link; + + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * Set up + */ + public function setUp() + { + $this->objectManager = new ObjectManager($this); + + $this->link = $this->objectManager->getObject('Magento\Ui\Component\Control\Link'); + } + + /** + * Run test getComponentName method + * + * @return void + */ + public function testGetComponentName() + { + $this->assertTrue($this->link->getComponentName() === Link::NAME); + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/FilterPoolTest.php b/app/code/Magento/Ui/Test/Unit/Component/FilterPoolTest.php deleted file mode 100644 index f12d71763da6ffb834c31e627825ed606ad993c8..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/Component/FilterPoolTest.php +++ /dev/null @@ -1,408 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Ui\Test\Unit\Component; - -use \Magento\Ui\Component\FilterPool; - -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\Filter\FilterPool as FilterPoolProvider; -use Magento\Ui\ContentType\ContentTypeFactory; - -/** - * Class ViewTest - */ -class FilterPoolTest extends \PHPUnit_Framework_TestCase -{ - /** - * Filter var - */ - const FILTER_VAR = 'filter'; - - /** - * @var TemplateContext|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextMock; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $renderContextMock; - - /** - * @var ContentTypeFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contentTypeFactoryMock; - - /** - * @var ConfigFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configFactoryMock; - - /** - * @var ConfigBuilderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configBuilderMock; - - /** - * @var \Magento\Ui\DataProvider\Factory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderFactoryMock; - - /** - * @var \Magento\Ui\DataProvider\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderManagerMock; - - /** - * @var FilterPoolProvider|\PHPUnit_Framework_MockObject_MockObject - */ - protected $filterPoolProviderMock; - - /** - * @var FilterPool - */ - protected $filterPool; - - /** - * Set up - * - * @return void - */ - protected function setUp() - { - $this->contextMock = $this->getMock( - 'Magento\Framework\View\Element\Template\Context', - [], - [], - '', - false - ); - $this->renderContextMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\Context', - ['getNamespace', 'getStorage', 'getRequestParam'], - [], - '', - false - ); - $this->contentTypeFactoryMock = $this->getMock( - 'Magento\Ui\ContentType\ContentTypeFactory', - [], - [], - '', - false - ); - $this->configFactoryMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\ConfigFactory', - ['create'], - [], - '', - false - ); - $this->configBuilderMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface', - [], - '', - false - ); - $this->dataProviderFactoryMock = $this->getMock( - 'Magento\Ui\DataProvider\Factory', - [], - [], - '', - false - ); - $this->dataProviderManagerMock = $this->getMock( - 'Magento\Ui\DataProvider\Manager', - [], - [], - '', - false - ); - $this->filterPoolProviderMock = $this->getMock( - 'Magento\Ui\Component\Filter\FilterPool', - ['getFilter'], - [], - '', - false - ); - - $this->filterPool = new FilterPool( - $this->contextMock, - $this->renderContextMock, - $this->contentTypeFactoryMock, - $this->configFactoryMock, - $this->configBuilderMock, - $this->dataProviderFactoryMock, - $this->dataProviderManagerMock, - $this->filterPoolProviderMock - ); - } - - /** - * Run test prepare method - * - * @return void - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - public function testPrepare() - { - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigInterface - * |\PHPUnit_Framework_MockObject_MockObject $configurationMock - */ - $configurationMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigInterface', - ['getParentName'], - '', - false - ); - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigStorageInterface - * |\PHPUnit_Framework_MockObject_MockObject $configStorageMock - */ - $configStorageMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigStorageInterface', - ['addComponentsData', 'getDataCollection', 'getMeta'], - '', - false - ); - /** - * @var \Magento\Framework\Data\Collection|\PHPUnit_Framework_MockObject_MockObject $dataCollectionMock - */ - $dataCollectionMock = $this->getMock( - 'Magento\Framework\Data\Collection', - ['setOrder'], - [], - '', - false - ); - - $this->renderContextMock->expects($this->at(0)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->renderContextMock->expects($this->at(1)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->configFactoryMock->expects($this->any()) - ->method('create') - ->will($this->returnValue($configurationMock)); - $this->renderContextMock->expects($this->any()) - ->method('getStorage') - ->will($this->returnValue($configStorageMock)); - $configStorageMock->expects($this->at(0)) - ->method('getDataCollection') - ->will($this->returnValue($dataCollectionMock)); - $configStorageMock->expects($this->at(1)) - ->method('getDataCollection') - ->will($this->returnValue($dataCollectionMock)); - - $metaData = [ - 'field-1' => 'value-1', - 'field-2' => 'value-2', - 'field-3' => 'value-3', - 'field-4' => 'value-4', - ]; - $meta = [ - 'fields' => $metaData, - ]; - $filters = $metaData; - - $configStorageMock->expects($this->any()) - ->method('getMeta') - ->will($this->returnValue($meta)); - $this->renderContextMock->expects($this->once()) - ->method('getRequestParam') - ->with(static::FILTER_VAR); - - $filterMock = $this->getMockForAbstractClass( - 'Magento\Ui\Component\Filter\FilterInterface', - ['getCondition'], - '', - false - ); - - $this->filterPoolProviderMock->expects($this->any()) - ->method('getFilter') - ->will($this->returnValue($filterMock)); - $filterMock->expects($this->any()) - ->method('getCondition') - ->will($this->returnValue(true)); - - $dataCollectionMock->expects($this->any()) - ->method('addFieldToFilter'); - - $this->assertNull($this->filterPool->prepare()); - } - - /** - * Run test getFields method - * - * @return void - */ - public function _testGetFields() - { - /** @var \Magento\Ui\Component\FilterPool|\PHPUnit_Framework_MockObject_MockObject $filterPool */ - $filterPool = $this->getMock( - 'Magento\Ui\Component\FilterPool', - ['getParentName'], - [ - $this->contextMock, - $this->renderContextMock, - $this->contentTypeFactoryMock, - $this->configFactoryMock, - $this->configBuilderMock, - $this->dataProviderFactoryMock, - $this->dataProviderManagerMock, - $this->filterPoolProviderMock - ], - '', - false - ); - $filterPool->expects($this->any()) - ->method('getParentName') - ->willReturn('parent'); - - $result = [ - 'field-1' => ['filterable' => 1], - 'field-4' => ['filterable' => 1], - ]; - $meta = [ - 'fields' => [ - 'field-1' => ['filterable' => true], - 'field-2' => ['filterable' => false], - 'field-3' => ['filterable' => false], - 'field-4' => ['filterable' => true], - ], - ]; - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigInterface - * |\PHPUnit_Framework_MockObject_MockObject $configurationMock - */ - $configMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigInterface', - [], - '', - false - ); - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigStorageInterface - * |\PHPUnit_Framework_MockObject_MockObject $configStorageMock - */ - $configStorageMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigStorageInterface', - ['addComponentsData', 'getDataCollection', 'getMeta'], - '', - false - ); - - $this->filterPool->setConfig($configMock); - - $this->renderContextMock->expects($this->any()) - ->method('getStorage') - ->will($this->returnValue($configStorageMock)); - $configStorageMock->expects($this->any()) - ->method('getMeta') - ->will($this->returnValue($meta)); - - $this->assertEquals($result, $filterPool->getFields()); - } - - /** - * Run test getActiveFilters method - * - * @return void - */ - public function _testGetActiveFilters() - { - $result = [ - 'field-1' => [ - 'title' => 'title-1', - 'current_display_value' => 'value-1', - ], - 'field-2' => [ - 'title' => 'title-2', - 'current_display_value' => 'value-2', - ], - 'field-3' => [ - 'title' => 'title-3', - 'current_display_value' => 'value-3', - ], - 'field-4' => [ - 'title' => 'title-4', - 'current_display_value' => 'value-4', - ], - ]; - $meta = [ - 'fields' => [ - 'field-1' => [ - 'filter_type' => true, - 'title' => 'title-1', - ], - 'field-2' => [ - 'filter_type' => true, - 'title' => 'title-2', - ], - 'field-3' => [ - 'filter_type' => true, - 'title' => 'title-3', - ], - 'field-4' => [ - 'filter_type' => true, - 'title' => 'title-4', - ], - ], - ]; - $filters = [ - 'field-1' => 'value-1', - 'field-2' => 'value-2', - 'field-3' => 'value-3', - 'field-4' => 'value-4', - ]; - - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigInterface - * |\PHPUnit_Framework_MockObject_MockObject $configurationMock - */ - $configMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigInterface', - [], - '', - false - ); - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigStorageInterface - * |\PHPUnit_Framework_MockObject_MockObject $configStorageMock - */ - $configStorageMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigStorageInterface', - ['addComponentsData', 'getDataCollection', 'getMeta'], - '', - false - ); - - $this->filterPool->setConfig($configMock); - - $this->renderContextMock->expects($this->any()) - ->method('getStorage') - ->will($this->returnValue($configStorageMock)); - $configStorageMock->expects($this->any()) - ->method('getMeta') - ->will($this->returnValue($meta)); - $this->dataHelperMock->expects($this->once()) - ->method('prepareFilterString') - ->will($this->returnValue($filters)); - $this->renderContextMock->expects($this->once()) - ->method('getRequestParam') - ->with(static::FILTER_VAR); - - $this->assertEquals($result, $this->filterPool->getActiveFilters()); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/Component/FilterTest.php b/app/code/Magento/Ui/Test/Unit/Component/FilterTest.php deleted file mode 100644 index 656070849515a734268911a185eb1f9d18aae239..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/Component/FilterTest.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\Component; - -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\Filter\FilterPool as FilterPoolProvider; -use Magento\Ui\ContentType\ContentTypeFactory; - -/** - * Class FilterTest - */ -class FilterTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var TemplateContext||\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextMock; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $renderContextMock; - - /** - * @var ContentTypeFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contentTypeFactoryMock; - - /** - * @var ConfigFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configFactoryMock; - - /** - * @var ConfigBuilderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configBuilderMock; - - /** - * @var \Magento\Ui\DataProvider\Factory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderFactoryMock; - - /** - * @var \Magento\Ui\DataProvider\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderManagerMock; - - /** - * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataHelperMock; - - /** - * @var FilterPoolProvider|\PHPUnit_Framework_MockObject_MockObject - */ - protected $filterPoolMock; - - /** - * @var \Magento\Ui\Component\FilterPool - */ - protected $filter; - - /** - * Set up - * - * @return void - */ - protected function setUp() - { - $this->contextMock = $this->getMock( - 'Magento\Framework\View\Element\Template\Context', - [], - [], - '', - false - ); - $this->renderContextMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\Context', - ['getNamespace', 'getStorage', 'getRequestParam'], - [], - '', - false - ); - $this->contentTypeFactoryMock = $this->getMock( - 'Magento\Ui\ContentType\ContentTypeFactory', - [], - [], - '', - false - ); - $this->configFactoryMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\ConfigFactory', - ['create'], - [], - '', - false - ); - $this->configBuilderMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface', - [], - '', - false - ); - $this->dataProviderFactoryMock = $this->getMock( - 'Magento\Ui\DataProvider\Factory', - [], - [], - '', - false - ); - $this->dataProviderManagerMock = $this->getMock( - 'Magento\Ui\DataProvider\Manager', - [], - [], - '', - false - ); - $this->filterPoolMock = $this->getMock( - 'Magento\Ui\Component\Filter\FilterPool', - ['getFilter'], - [], - '', - false - ); - - $this->filter = new \Magento\Ui\Component\FilterPool( - $this->contextMock, - $this->renderContextMock, - $this->contentTypeFactoryMock, - $this->configFactoryMock, - $this->configBuilderMock, - $this->dataProviderFactoryMock, - $this->dataProviderManagerMock, - $this->filterPoolMock - ); - } - - /** - * Run test prepare method - * - * @return void - */ - public function testPrepare() - { - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigInterface - * |\PHPUnit_Framework_MockObject_MockObject $configurationMock - */ - $configurationMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigInterface', - [], - '', - false - ); - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigStorageInterface - * |\PHPUnit_Framework_MockObject_MockObject $configStorageMock - */ - $configStorageMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigStorageInterface', - ['addComponentsData', 'getDataCollection', 'getMeta'], - '', - false - ); - - $this->renderContextMock->expects($this->at(0)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->renderContextMock->expects($this->at(1)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->configFactoryMock->expects($this->any()) - ->method('create') - ->will($this->returnValue($configurationMock)); - - $this->renderContextMock->expects($this->any()) - ->method('getStorage') - ->will($this->returnValue($configStorageMock)); - $configStorageMock->expects($this->once()) - ->method('addComponentsData') - ->with($configurationMock); - - $this->assertNull($this->filter->prepare()); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/Component/Listing/Columns/ColumnTest.php b/app/code/Magento/Ui/Test/Unit/Component/Listing/Columns/ColumnTest.php new file mode 100644 index 0000000000000000000000000000000000000000..98005246955763c90120fd66e06ff8f9eabb0a1a --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/Listing/Columns/ColumnTest.php @@ -0,0 +1,164 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Test\Unit\Component\Listing\Columns; + +use Magento\Ui\Component\Listing\Columns\Column; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; + +/** + * Class ColumnTest + */ +class ColumnTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * Set up + */ + public function setUp() + { + $this->objectManager = new ObjectManager($this); + + $this->contextMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\ContextInterface', + [], + '', + false, + true, + true, + [] + ); + } + + /** + * Run test getComponentName method + * + * @return void + */ + public function testGetComponentName() + { + $column = $this->objectManager->getObject( + 'Magento\Ui\Component\Listing\Columns\Column', + [ + 'context' => $this->contextMock, + 'data' => [ + 'js_config' => [ + 'extends' => 'test_config_extends' + ], + 'config' => [ + 'dataType' => 'testType' + ] + ] + ] + ); + + $this->assertEquals($column->getComponentName(), Column::NAME . '.testType'); + } + + /** + * Run test prepareItems method + * + * @return void + */ + public function testPrepareItems() + { + $testItems = ['item1','item2', 'item3']; + $column = $this->objectManager->getObject('Magento\Ui\Component\Listing\Columns\Column'); + + $this->assertEquals($testItems, $column->prepareItems($testItems)); + } + + /** + * Run test prepare method + * + * @return void + */ + public function testPrepare() + { + $data = [ + 'name' => 'test_name', + 'js_config' => ['extends' => 'test_config_extends'], + 'config' => ['dataType' => 'test_type', 'sortable' => true] + ]; + + /** @var UiComponentFactory|\PHPUnit_Framework_MockObject_MockObject $uiComponentFactoryMock */ + $uiComponentFactoryMock = $this->getMock( + 'Magento\Framework\View\Element\UiComponentFactory', + [], + [], + '', + false + ); + + /** @var UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject $wrappedComponentMock */ + $wrappedComponentMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponentInterface', + [], + '', + false + ); + /** @var DataProviderInterface|\PHPUnit_Framework_MockObject_MockObject $dataProviderMock */ + $dataProviderMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface', + [], + '', + false + ); + + $this->contextMock->expects($this->atLeastOnce()) + ->method('getNamespace') + ->willReturn('test_namespace'); + $this->contextMock->expects($this->atLeastOnce()) + ->method('getDataProvider') + ->willReturn($dataProviderMock); + $this->contextMock->expects($this->atLeastOnce()) + ->method('getRequestParam') + ->with('sorting') + ->willReturn(['field' => 'test_name', 'direction' => 'asc']); + $this->contextMock->expects($this->atLeastOnce()) + ->method('addComponentDefinition') + ->with(Column::NAME . '.test_type', ['extends' => 'test_config_extends']); + + $dataProviderMock->expects($this->once()) + ->method('addOrder') + ->with('test_name', 'ASC'); + + $uiComponentFactoryMock->expects($this->once()) + ->method('create') + ->with('test_name', 'test_type', array_merge(['context' => $this->contextMock], $data)) + ->willReturn($wrappedComponentMock); + + $wrappedComponentMock->expects($this->once()) + ->method('getContext') + ->willReturn($this->contextMock); + $wrappedComponentMock->expects($this->once()) + ->method('prepare'); + + /** @var Column $column */ + $column = $this->objectManager->getObject( + 'Magento\Ui\Component\Listing\Columns\Column', + [ + 'context' => $this->contextMock, + 'uiComponentFactory' => $uiComponentFactoryMock, + 'data' => $data + ] + ); + + $column->prepare(); + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/Listing/ColumnsTest.php b/app/code/Magento/Ui/Test/Unit/Component/Listing/ColumnsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f6769ba8e306e3f761cf54f135779d0c2815d502 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/Listing/ColumnsTest.php @@ -0,0 +1,136 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Test\Unit\Component\Listing; + +use Magento\Ui\Component\Listing\Columns; +use Magento\Ui\Component\Listing\Columns\Column; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; + +/** + * Class ColumnsTest + */ +class ColumnsTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * Set up + */ + public function setUp() + { + $this->objectManager = new ObjectManager($this); + + $this->contextMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\ContextInterface', + [], + '', + false, + true, + true, + [] + ); + } + + /** + * Run test getComponentName method + * + * @return void + */ + public function testGetComponentName() + { + $columns = $this->objectManager->getObject( + 'Magento\Ui\Component\Listing\Columns', + [ + 'context' => $this->contextMock, + 'data' => [ + 'js_config' => [ + 'extends' => 'test_config_extends' + ], + 'config' => [ + 'dataType' => 'testType' + ] + ] + ] + ); + + $this->assertEquals($columns->getComponentName(), Columns::NAME); + } + + /** + * Run test prepare method + * + * @return void + */ + public function testPrepare() + { + /** @var Column|\PHPUnit_Framework_MockObject_MockObject $componentMock */ + $columnMock = $this->getMock( + 'Magento\Ui\Component\Listing\Columns\Column', + [], + [], + '', + false + ); + /** @var DataProviderInterface|\PHPUnit_Framework_MockObject_MockObject $dataProviderMock */ + $dataProviderMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface', + [], + '', + false + ); + + $data = [ + 'name' => 'test_name', + 'js_config' => ['extends' => 'test_config_extends'], + 'config' => ['dataType' => 'test_type', 'sortable' => true] + ]; + + $this->contextMock->expects($this->once()) + ->method('getDataProvider') + ->willReturn($dataProviderMock); + $this->contextMock->expects($this->once()) + ->method('addComponentDefinition') + ->with('columns', ['extends' => 'test_config_extends']); + + $dataProviderMock->expects($this->once()) + ->method('getFieldMetaInfo') + ->with('test_name', 'test_column_name') + ->willReturn(['test_meta' => 'test_meta_value']); + + $columnMock->expects($this->once()) + ->method('getName') + ->willReturn('test_column_name'); + $columnMock->expects($this->once()) + ->method('getData') + ->with('config') + ->willReturn(['test_config_data' => 'test_config_value']); + $columnMock->expects($this->once()) + ->method('setData') + ->with('config', ['test_config_data' => 'test_config_value', 'test_meta' => 'test_meta_value']); + + /** @var Columns $columns */ + $columns = $this->objectManager->getObject( + 'Magento\Ui\Component\Listing\Columns', + [ + 'components' => [$columnMock], + 'context' => $this->contextMock, + 'data' => $data + ] + ); + + $columns->prepare(); + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php b/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php index e5f795227c825879d26bb72cd441cdb7c32eaa22..dcc49cf83f36d8c2a6734adf26bb8d5726357137 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php @@ -3,200 +3,218 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Ui\Test\Unit\Component; -use \Magento\Ui\Component\Listing; - -use Magento\Framework\View\Element\Template\Context; -use Magento\Ui\Component\Control\ActionPool; -use Magento\Ui\Component\Listing\OptionsFactory; -use Magento\Ui\Component\Listing\RowPool; -use Magento\Ui\Context\ConfigurationFactory; +use Magento\Ui\Component\Listing; +use Magento\Ui\Component\Listing\Columns; +use Magento\Ui\Component\Listing\Columns\Column; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; /** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * Class ListingTest */ class ListingTest extends \PHPUnit_Framework_TestCase { /** - * @var ActionPool|\PHPUnit_Framework_MockObject_MockObject - */ - protected $actionPool; - - /** - * @var OptionsFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $optionsFactory; - - /** - * @var RowPool|\PHPUnit_Framework_MockObject_MockObject - */ - protected $rowPool; - - /** - * @var Context - */ - protected $templateContext; - - /** - * @var \Magento\Framework\Stdlib\DateTime\Timezone|\PHPUnit_Framework_MockObject_MockObject + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $localeDate; + protected $contextMock; /** - * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ObjectManager */ - protected $urlBuilder; + protected $objectManager; /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigFactory|\PHPUnit_Framework_MockObject_MockObject + * Set up */ - protected $configurationFactory; + public function setUp() + { + $this->objectManager = new ObjectManager($this); - /** - * @var \Magento\Framework\View\Element\UiComponent\Context |\PHPUnit_Framework_MockObject_MockObject - */ - protected $renderContext; + $this->contextMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\ContextInterface', + [], + '', + false, + true, + true, + [] + ); + } /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + * Run test getComponentName method + * + * @return void */ - protected $objectManagerHelper; + public function testGetComponentName() + { + /** @var Listing $listing */ + $listing = $this->objectManager->getObject( + 'Magento\Ui\Component\Listing', + [ + 'context' => $this->contextMock, + 'data' => [] + ] + ); - /** - * @var \Magento\Ui\Context\Configuration |\PHPUnit_Framework_MockObject_MockObject - */ - protected $configuration; + $this->assertTrue($listing->getComponentName() === Listing::NAME); + } /** - * @var \Magento\Ui\Context\ConfigurationStorage |\PHPUnit_Framework_MockObject_MockObject + * Run test prepare method + * + * @return void */ - protected $configStorage; + public function testPrepare() + { + $buttons = [ + 'button1' => 'button1', + 'button2' => 'button2' + ]; + /** @var Listing $listing */ + $listing = $this->objectManager->getObject( + 'Magento\Ui\Component\Listing', + [ + 'context' => $this->contextMock, + 'data' => [ + 'js_config' => [ + 'extends' => 'test_config_extends', + 'testData' => 'testValue', + ], + 'buttons' => $buttons + ] + ] + ); - /** - * @var \Magento\Ui\ContentType\ContentTypeFactory |\PHPUnit_Framework_MockObject_MockObject - */ - protected $contentTypeFactory; + $this->contextMock->expects($this->once()) + ->method('getNamespace') + ->willReturn(Listing::NAME); + $this->contextMock->expects($this->once()) + ->method('addComponentDefinition') + ->with($listing->getComponentName(), ['testData' => 'testValue']); + $this->contextMock->expects($this->once()) + ->method('addButtons') + ->with($buttons, $listing); + + $listing->prepare(); + } /** - * @var Listing + * Run test getDataSourceData method + * + * @return void + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - protected $listingView; - - public function setUp() + public function testGetDataSourceData() { - $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->actionPool = $this->getMock('\Magento\Ui\Component\Control\ActionPool', [], [], '', false); - $this->optionsFactory = $this->getMock('\Magento\Ui\Component\Listing\OptionsFactory', [], [], '', false); - $this->rowPool = $this->getMock('\Magento\Ui\Component\Listing\RowPool', [], [], '', false); - $this->renderContext = $this->getMock('\Magento\Framework\View\Element\UiComponent\Context', [], [], '', false); - $this->templateContext = $this->getMock( - 'Magento\Framework\View\Element\Template\Context', - [], + $result = [ + [ + 'type' => 'test_component_name', + 'name' => 'test_name', + 'dataScope' => 'test_namespace', + 'config' => [ + 'data' => [ + 'items' => ['data'] + ], + 'totalCount' => 20, + 'testConfig' => 'testConfigValue', + 'params' => [ + 'namespace' => 'test_namespace' + ] + ] + ] + ]; + + /** @var DataSourceInterface|\PHPUnit_Framework_MockObject_MockObject $dataSourceMock */ + $dataSourceMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\DataSourceInterface', [], '', false ); - $this->configStorage = $this->getMock( - 'Magento\Ui\Context\ConfigurationStorage', - [], + /** @var DataProviderInterface|\PHPUnit_Framework_MockObject_MockObject $dataProviderMock */ + $dataProviderMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface', [], '', false ); - $this->localeDate = $this->getMock('Magento\Framework\Stdlib\DateTime\Timezone', [], [], '', false); - $this->urlBuilder = $this->getMock('Magento\Backend\Model\Url', ['getUrl'], [], '', false); - $this->templateContext->expects($this->once()) - ->method('getLocaleDate') - ->willReturn($this->localeDate); - $this->templateContext->expects($this->once()) - ->method('getUrlBuilder') - ->willReturn($this->urlBuilder); - $this->contentTypeFactory = $this->getMock('Magento\Ui\ContentType\ContentTypeFactory', [], [], '', false); - $this->configurationFactory = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\ConfigFactory', + /** @var Columns|\PHPUnit_Framework_MockObject_MockObject $columnsMock */ + $columnsMock = $this->getMock( + 'Magento\Ui\Component\Listing\Columns', [], [], '', false ); - $configurationBuilder = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface', - ['toJson'], + /** @var Column|\PHPUnit_Framework_MockObject_MockObject $columnMock */ + $columnMock = $this->getMock( + 'Magento\Ui\Component\Listing\Columns\Column', + [], [], '', false ); - $this->configuration = $this->getMock('Magento\Ui\Context\Configuration', [], [], '', false); - $this->renderContext->expects($this->any()) - ->method('getStorage') - ->willReturn($this->configStorage); - $this->listingView = $this->objectManagerHelper->getObject( - '\Magento\Ui\Component\Listing', + /** @var Listing $listing */ + $listing = $this->objectManager->getObject( + 'Magento\Ui\Component\Listing', [ - 'context' => $this->templateContext, - 'renderContext' => $this->renderContext, - 'contentTypeFactory' => $this->contentTypeFactory, - 'configFactory' => $this->configurationFactory, - 'configBuilder' => $configurationBuilder, - 'optionsFactory' => $this->optionsFactory, - 'actionPool' => $this->actionPool, - 'dataProviderRowPool' => $this->rowPool + 'context' => $this->contextMock, + 'components' => [$dataSourceMock, $columnsMock], + 'data' => [ + 'js_config' => [ + 'extends' => 'test_config_extends', + 'testData' => 'testValue', + ] + ] ] ); - } - - protected function prepareMeta() - { - $meta = ['fields' => [['data_type' => 'date', 'options_provider' => 'provider', 'options' => ['option1']]]]; - $this->listingView->setData('meta', $meta); - $this->localeDate->expects($this->any()) - ->method('getDateTimeFormat') - ->with(\IntlDateFormatter::MEDIUM) - ->willReturn('format_type'); - $options = $this->getMock('Magento\Cms\Ui\DataProvider\Page\Options\PageLayout', [], [], '', false); - $this->optionsFactory->expects($this->any()) - ->method('create') - ->with('provider') - ->willReturn($options); - $options->expects($this->any()) - ->method('getOptions') - ->with(['option1']) - ->willReturn(['option1']); - } - - public function testPrepare() - { - $this->prepareMeta(); - $config = [ - 'page_actions' => [ - 'add' => [ - 'name' => 'add', - 'label' => __('Add New'), - 'class' => 'primary', - 'url' => 'http://some.url', - ], - ], - ]; - $this->urlBuilder->expects($this->at(0)) - ->method('getUrl') - ->with('*/*/new') - ->willReturn('http://mage.local/category/new'); - $dataCollection = $this->getMock('Magento\Framework\Data\CollectionDataSourceInterface', [], [], '', false); - $this->listingView->setData('configuration', $config); - $this->listingView->setData('name', 'someName'); - $this->listingView->setData('dataSource', $dataCollection); - $this->actionPool->expects($this->once()) - ->method('add') - ->with('add', $config['page_actions']['add'], $this->listingView); - - $this->configurationFactory->expects($this->once()) - ->method('create') - ->willReturn($this->configuration); - - $this->assertNull($this->listingView->prepare()); + $columnsMock->expects($this->once()) + ->method('getChildComponents') + ->willReturn([$columnMock]); + + $dataSourceMock->expects($this->any()) + ->method('getDataProvider') + ->willReturn($dataProviderMock); + $dataProviderMock->expects($this->once()) + ->method('getData') + ->willReturn(['items' => ['data']]); + + $columnMock->expects($this->once()) + ->method('prepareItems') + ->with(['data']); + + $dataSourceMock->expects($this->once()) + ->method('getComponentName') + ->willReturn('test_component_name'); + $dataSourceMock->expects($this->once()) + ->method('getName') + ->willReturn('test_name'); + $dataSourceMock->expects($this->once()) + ->method('getContext') + ->willReturn($this->contextMock); + + $this->contextMock->expects($this->any()) + ->method('getNamespace') + ->willReturn('test_namespace'); + + $dataProviderMock->expects($this->once()) + ->method('count') + ->willReturn(20); + + $dataSourceMock->expects($this->once()) + ->method('getData') + ->with('config') + ->willReturn(['testConfig' => 'testConfigValue']); + + $this->assertEquals($listing->getDataSourceData(), $result); } } diff --git a/app/code/Magento/Ui/Test/Unit/Component/MassAction/Columns/ColumnTest.php b/app/code/Magento/Ui/Test/Unit/Component/MassAction/Columns/ColumnTest.php new file mode 100644 index 0000000000000000000000000000000000000000..43b9271d4e013ab291e2e0b0346298456ef6be12 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/MassAction/Columns/ColumnTest.php @@ -0,0 +1,126 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Test\Unit\Component\MassAction\Columns; + +use Magento\Ui\Component\MassAction\Columns\Column; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + +/** + * Class ColumnTest + */ +class ColumnTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var Column + */ + protected $column; + + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * Set up + */ + public function setUp() + { + $this->objectManager = new ObjectManager($this); + + $this->contextMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\ContextInterface', + [], + '', + false, + true, + true, + [] + ); + + $this->column = $this->objectManager->getObject( + 'Magento\Ui\Component\MassAction\Columns\Column', + [ + 'context' => $this->contextMock, + 'data' => [ + 'js_config' => [ + 'extends' => 'test_config_extends' + ] + ] + ] + ); + } + + /** + * Run test getComponentName method + * + * @return void + */ + public function testGetComponentName() + { + $this->assertTrue($this->column->getComponentName() === Column::NAME); + } + + /** + * Run test prepareItems method + * + * @return void + */ + public function testPrepareItems() + { + $testItems = ['item1','item2', 'item3']; + + $this->assertEquals($testItems, $this->column->prepareItems($testItems)); + } + + /** + * Run test prepare method + * + * @return void + */ + public function testPrepare() + { + $this->column = $this->objectManager->getObject( + 'Magento\Ui\Component\MassAction\Columns\Column', + [ + 'context' => $this->contextMock, + 'data' => [ + 'js_config' => [] + ] + ] + ); + + $this->contextMock->expects($this->once()) + ->method('getNamespace') + ->willReturn('test_namespace'); + $this->contextMock->expects($this->once()) + ->method('addComponentDefinition') + ->with($this->column->getComponentName(), ['extends' => 'test_namespace']); + + $this->column->prepare(); + } + + /** + * Run test prepare method + * + * @return void + */ + public function testPrepareExtendsFromConfig() + { + $this->contextMock->expects($this->never()) + ->method('getNamespace'); + $this->contextMock->expects($this->once()) + ->method('addComponentDefinition') + ->with($this->column->getComponentName(), ['extends' => 'test_config_extends']); + + $this->column->prepare(); + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/MassActionTest.php b/app/code/Magento/Ui/Test/Unit/Component/MassActionTest.php deleted file mode 100644 index f66f2d6a9de87f2d2fadb1c858ee6b9d2b40de4f..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/Component/MassActionTest.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\Component; - -use \Magento\Ui\Component\MassAction; - -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\ContentType\ContentTypeFactory; - -class MassActionTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var TemplateContext||\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextMock; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $renderContextMock; - - /** - * @var ContentTypeFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contentTypeFactoryMock; - - /** - * @var ConfigFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configFactoryMock; - - /** - * @var ConfigBuilderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configBuilderMock; - - /** - * @var \Magento\Ui\DataProvider\Factory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderFactoryMock; - - /** - * @var \Magento\Ui\DataProvider\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderManagerMock; - - /** - * @var MassAction - */ - protected $view; - - /** - * Set up - * - * @return void - */ - protected function setUp() - { - $this->contextMock = $this->getMock( - 'Magento\Framework\View\Element\Template\Context', - [], - [], - '', - false - ); - $this->renderContextMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\Context', - ['getNamespace', 'getStorage', 'getRequestParam'], - [], - '', - false - ); - $this->contentTypeFactoryMock = $this->getMock( - 'Magento\Ui\ContentType\ContentTypeFactory', - [], - [], - '', - false - ); - $this->configFactoryMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\ConfigFactory', - ['create'], - [], - '', - false - ); - $this->configBuilderMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface', - [], - '', - false - ); - $this->dataProviderFactoryMock = $this->getMock( - 'Magento\Ui\DataProvider\Factory', - [], - [], - '', - false - ); - $this->dataProviderManagerMock = $this->getMock( - 'Magento\Ui\DataProvider\Manager', - [], - [], - '', - false - ); - - $this->view = new MassAction( - $this->contextMock, - $this->renderContextMock, - $this->contentTypeFactoryMock, - $this->configFactoryMock, - $this->configBuilderMock, - $this->dataProviderFactoryMock, - $this->dataProviderManagerMock - ); - } - - /** - * Run test prepare method - * - * @return void - */ - public function testPrepare() - { - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigInterface - * |\PHPUnit_Framework_MockObject_MockObject $configurationMock - */ - $configurationMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigInterface', - [], - '', - false - ); - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigStorageInterface - * |\PHPUnit_Framework_MockObject_MockObject $configStorageMock - */ - $configStorageMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigStorageInterface', - ['addComponentsData', 'getDataCollection'], - '', - false - ); - - $this->renderContextMock->expects($this->at(0)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->renderContextMock->expects($this->at(1)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->configFactoryMock->expects($this->any()) - ->method('create') - ->will($this->returnValue($configurationMock)); - - $this->renderContextMock->expects($this->any()) - ->method('getStorage') - ->will($this->returnValue($configStorageMock)); - - $configStorageMock->expects($this->once()) - ->method('addComponentsData') - ->with($configurationMock); - - $this->assertNull($this->view->prepare()); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php b/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php index e8cd28a27665a09b164e93c2f76c58e72ffd1ed7..fd4c63c3b28870ad1a60068d66ee86eb52c6291a 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php @@ -5,182 +5,164 @@ */ namespace Magento\Ui\Test\Unit\Component; -use \Magento\Ui\Component\Paging; - -use Magento\Framework\View\Asset\Repository; -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\ContentType\ContentTypeFactory; +use Magento\Ui\Component\Paging; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; +/** + * Class PagingTest + */ class PagingTest extends \PHPUnit_Framework_TestCase { /** - * @var Paging - */ - protected $view; - - /** - * @var ConfigBuilderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configurationBuilderMock; - - /** - * @var TemplateContext|\PHPUnit_Framework_MockObject_MockObject + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $contextMock; /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $renderContextMock; - - /** - * @var ContentTypeFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contentTypeFactoryMock; - - /** - * @var ConfigFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configFactoryMock; - - /** - * @var ConfigBuilderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ObjectManager */ - protected $configBuilderMock; + protected $objectManager; /** - * @var \Magento\Ui\DataProvider\Factory|\PHPUnit_Framework_MockObject_MockObject + * Set up */ - protected $dataProviderFactoryMock; - - /** - * @var \Magento\Ui\DataProvider\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderManagerMock; - - /** - * @var Repository|\PHPUnit_Framework_MockObject_MockObject - */ - protected $assetRepoMock; - public function setUp() { - $this->renderContextMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\Context', - ['getNamespace', 'getStorage', 'getRequestParam'], - [], - '', - false - ); - $this->contextMock = $this->getMock( - 'Magento\Framework\View\Element\Template\Context', - ['getAssetRepository'], - [], - '', - false - ); - $this->contentTypeFactoryMock = $this->getMock('Magento\Ui\ContentType\ContentTypeFactory', [], [], '', false); - $this->configurationBuilderMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface' - ); - $this->assetRepoMock = $this->getMock('Magento\Framework\View\Asset\Repository', [], [], '', false); - $this->contextMock->expects($this->any())->method('getAssetRepository')->willReturn($this->assetRepoMock); + $this->objectManager = new ObjectManager($this); - $this->configFactoryMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\ConfigFactory', - ['create'], - [], - '', - false - ); - $this->configBuilderMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface', - [], - '', - false - ); - $this->dataProviderFactoryMock = $this->getMock( - 'Magento\Ui\DataProvider\Factory', - [], - [], - '', - false - ); - $this->dataProviderManagerMock = $this->getMock( - 'Magento\Ui\DataProvider\Manager', - [], + $this->contextMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\ContextInterface', [], '', - false + false, + true, + true, + [] ); + } - $this->view = new \Magento\Ui\Component\Paging( - $this->contextMock, - $this->renderContextMock, - $this->contentTypeFactoryMock, - $this->configFactoryMock, - $this->configBuilderMock, - $this->dataProviderFactoryMock, - $this->dataProviderManagerMock + /** + * Run test getComponentName method + * + * @return void + */ + public function testGetComponentName() + { + /** @var Paging $listing */ + $paging = $this->objectManager->getObject( + 'Magento\Ui\Component\Paging', + [ + 'context' => $this->contextMock, + 'data' => [] + ] ); + + $this->assertTrue($paging->getComponentName() === Paging::NAME); } + /** + * Run test prepare method + * + * @return void + */ public function testPrepare() { - $paramsSize = 20; - $paramsPage = 1; - $nameSpace = 'namespace'; - $configurationMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigInterface', - ['getData'], - '', - false - ); - $this->renderContextMock->expects($this->any())->method('getNamespace')->willReturn($nameSpace); - $this->configFactoryMock->expects($this->once())->method('create')->willReturn($configurationMock); - - $storageMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigStorageInterface' + $resultData = [ + 'js_config' => [ + 'extends' => 'test_config_extends', + 'testData' => 'testValue' + ], + 'config' => [ + 'options' => [ + [ + 'value' => 20, + 'label' => 20 + ], + [ + 'value' => 30, + 'label' => 30 + ], + [ + 'value' => 50, + 'label' => 50 + ], + [ + 'value' => 100, + 'label' => 100 + ], + [ + 'value' => 200, + 'label' => 200 + ], + [ + 'value' => 20, + 'label' => 'options1' + ], + [ + 'value' => 40, + 'label' => 'options2' + ], + ], + 'pageSize' => 20, + 'current' => 2 + ] + ]; + + /** @var Paging $paging */ + $paging = $this->objectManager->getObject( + 'Magento\Ui\Component\Paging', + [ + 'context' => $this->contextMock, + 'data' => [ + 'js_config' => [ + 'extends' => 'test_config_extends', + 'testData' => 'testValue', + ], + 'config' => [ + 'options' => [ + 'options1' => [ + 'label' => 'options1', + 'value' => '20' + ], + 'options2' => [ + 'label' => 'options2', + 'value' => '40' + ] + ], + 'current' => 2, + 'pageSize' => 20 + ] + ] + ] ); - $dataCollectionMock = $this->getMockForAbstractClass( - '\Magento\Framework\Data\CollectionDataSourceInterface', + /** @var DataProviderInterface|\PHPUnit_Framework_MockObject_MockObject $dataProviderMock */ + $dataProviderMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface', [], '', - false, - true, - true, - ['setPageSize', 'setCurPage'] + false ); - $this->renderContextMock->expects($this->any())->method('getStorage')->willReturn($storageMock); - - $storageMock->expects($this->once())->method('getDataCollection')->willReturn($dataCollectionMock); + $this->contextMock->expects($this->once()) + ->method('getRequestParam') + ->with('paging') + ->willReturn(['pageSize' => 5, 'current' => 3]); + $this->contextMock->expects($this->once()) + ->method('getDataProvider') + ->willReturn($dataProviderMock); - $configurationMock->expects($this->at(0))->method('getData')->with('current')->willReturn($paramsPage); + $dataProviderMock->expects($this->once()) + ->method('setLimit') + ->with(3, 5); - $configurationMock->expects($this->at(1))->method('getData')->with('pageSize')->willReturn($paramsSize); - $this->renderContextMock->expects($this->atLeastOnce()) - ->method('getRequestParam') - ->willReturnMap( - [ - ['page', $paramsPage, $paramsPage], - ['limit', $paramsSize, $paramsSize], - ] - ); + $this->contextMock->expects($this->once()) + ->method('addComponentDefinition') + ->with($paging->getComponentName(), ['extends' => 'test_config_extends', 'testData' => 'testValue']); - $dataCollectionMock->expects($this->any()) - ->method('setPageSize') - ->with($paramsSize) - ->willReturnSelf(); - $dataCollectionMock->expects($this->any()) - ->method('setCurPage') - ->with($paramsPage) - ->willReturnSelf(); + $paging->prepare(); - $this->assertNull($this->view->prepare()); + $this->assertEquals($paging->getData(), $resultData); } } diff --git a/app/code/Magento/Ui/Test/Unit/Component/SortingTest.php b/app/code/Magento/Ui/Test/Unit/Component/SortingTest.php deleted file mode 100644 index 5c7f02a31dc63b71f9b1db2fea3080a8fbef7972..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/Component/SortingTest.php +++ /dev/null @@ -1,211 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\Component; - -use \Magento\Ui\Component\Sorting; - -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\ContentType\ContentTypeFactory; - -class SortingTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var TemplateContext||\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextMock; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $renderContextMock; - - /** - * @var ContentTypeFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contentTypeFactoryMock; - - /** - * @var ConfigFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configFactoryMock; - - /** - * @var ConfigBuilderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configBuilderMock; - - /** - * @var \Magento\Ui\DataProvider\Factory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderFactoryMock; - - /** - * @var \Magento\Ui\DataProvider\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProviderManagerMock; - - /** - * @var Sorting - */ - protected $view; - - /** - * Set up - * - * @return void - */ - protected function setUp() - { - $this->contextMock = $this->getMock( - 'Magento\Framework\View\Element\Template\Context', - [], - [], - '', - false - ); - $this->renderContextMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\Context', - ['getNamespace', 'getStorage', 'getRequestParam'], - [], - '', - false - ); - $this->contentTypeFactoryMock = $this->getMock( - 'Magento\Ui\ContentType\ContentTypeFactory', - [], - [], - '', - false - ); - $this->configFactoryMock = $this->getMock( - 'Magento\Framework\View\Element\UiComponent\ConfigFactory', - ['create'], - [], - '', - false - ); - $this->configBuilderMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface', - [], - '', - false - ); - $this->dataProviderFactoryMock = $this->getMock( - 'Magento\Ui\DataProvider\Factory', - [], - [], - '', - false - ); - $this->dataProviderManagerMock = $this->getMock( - 'Magento\Ui\DataProvider\Manager', - [], - [], - '', - false - ); - - $this->view = new Sorting( - $this->contextMock, - $this->renderContextMock, - $this->contentTypeFactoryMock, - $this->configFactoryMock, - $this->configBuilderMock, - $this->dataProviderFactoryMock, - $this->dataProviderManagerMock - ); - } - - /** - * Run test prepare method - * - * @return void - */ - public function testPrepare() - { - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigInterface - * |\PHPUnit_Framework_MockObject_MockObject $configurationMock - */ - $configurationMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigInterface', - [], - '', - false - ); - /** - * @var \Magento\Framework\View\Element\UiComponent\ConfigStorageInterface - * |\PHPUnit_Framework_MockObject_MockObject $configStorageMock - */ - $configStorageMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponent\ConfigStorageInterface', - ['addComponentsData', 'getDataCollection'], - '', - false - ); - - $dataCollectionMock = $this->getMockForAbstractClass( - 'Magento\Framework\Api\CriteriaInterface', - ['addOrder'], - '', - false - ); - - $this->renderContextMock->expects($this->at(0)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->renderContextMock->expects($this->at(1)) - ->method('getNamespace') - ->will($this->returnValue('namespace')); - $this->configFactoryMock->expects($this->any()) - ->method('create') - ->will($this->returnValue($configurationMock)); - - $this->renderContextMock->expects($this->any()) - ->method('getStorage') - ->will($this->returnValue($configStorageMock)); - - $configStorageMock->expects($this->once()) - ->method('addComponentsData') - ->with($configurationMock); - - $configurationMock->expects($this->at(0)) - ->method('getData') - ->with('field') - ->will($this->returnValue('field')); - - $configurationMock->expects($this->at(1)) - ->method('getData') - ->with('direction') - ->will($this->returnValue('direction')); - - $this->renderContextMock->expects($this->any()) - ->method('getStorage') - ->will($this->returnValue($configStorageMock)); - - $configStorageMock->expects($this->once()) - ->method('getDataCollection') - ->will($this->returnValue($dataCollectionMock)); - - $dataCollectionMock->expects($this->once()) - ->method('addOrder') - ->with('field', 'FIELD'); - - $this->renderContextMock->expects($this->any()) - ->method('getRequestParam') - ->will($this->returnValue('field')); - - $this->renderContextMock->expects($this->any()) - ->method('getRequestParam') - ->will($this->returnValue('direction')); - - $this->assertNull($this->view->prepare()); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/ContentType/Builder/ConfigJsonTest.php b/app/code/Magento/Ui/Test/Unit/ContentType/Builder/ConfigJsonTest.php deleted file mode 100644 index 47e6d0ad983f69d450086e0e6689cb625dfe214b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/ContentType/Builder/ConfigJsonTest.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\ContentType\Builder; - -use \Magento\Ui\ContentType\Builder\ConfigJson; - -/** - * Class ConfigJsonTest - */ -class ConfigJsonTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var ConfigJson - */ - protected $builder; - - public function testToJson() - { - $this->builder = new ConfigJson(); - $result = ['name' => 'resultName', 'parent_name' => 'resultParentName']; - $configurationMock = $this->getMock( - 'Magento\Ui\Context\Configuration', - ['getData', 'getName', 'getParentName'], - [], - '', - false - ); - $configurationMock->expects($this->once())->method('getData')->willReturn($result); - $configurationMock->expects($this->once())->method('getName')->willReturn($result['name']); - $configurationMock->expects($this->once())->method('getParentName')->willReturn($result['parent_name']); - $this->assertEquals(json_encode($result), $this->builder->toJson($configurationMock)); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/ContentType/Builder/ConfigStorageJsonTest.php b/app/code/Magento/Ui/Test/Unit/ContentType/Builder/ConfigStorageJsonTest.php deleted file mode 100644 index 22511628d15e2631c499c186dbb91b0bf291d5fe..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/ContentType/Builder/ConfigStorageJsonTest.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\ContentType\Builder; - -use \Magento\Ui\ContentType\Builder\ConfigStorageJson; - -/** - * Class ConfigStorageJsonTest - */ -class ConfigStorageJsonTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var ConfigStorageJson - */ - protected $builder; - - public function testToJson() - { - $this->builder = new ConfigStorageJson(); - $name = 'name'; - $data = []; - $parentName = 'parentName'; - $dataSource = [ - 'data' => null, - ]; - $result = [ - 'config' => ['components' => [$name => $data], 'globalData' => ['globalData']], - 'meta' => null, - 'name' => $name, - 'parent_name' => $parentName, - 'data' => null, - 'dump' => ['extenders' => []], - ]; - - $rootComponentMock = $this->getMock( - 'Magento\Ui\Context\Configuration', - ['getName', 'getParentName', 'getData'], - [], - '', - false - ); - $storageMock = $this->getMock( - 'Magento\Ui\Context\ConfigurationStorage', - ['getComponentsData', 'getGlobalData', 'getMeta', 'getDataSource'], - [], - '', - false - ); - - $storageMock->expects($this->once()) - ->method('getComponentsData') - ->with($parentName) - ->will($this->returnValue($rootComponentMock)); - $rootComponentMock->expects($this->any())->method('getName')->willReturn($result['name']); - $rootComponentMock->expects($this->once())->method('getParentName')->willReturn($result['parent_name']); - $rootComponentMock->expects($this->once()) - ->method('getData') - ->willReturn($data); - $storageMock->expects($this->once())->method('getGlobalData')->willReturn($result['config']); - $storageMock->expects($this->once())->method('getDataSource')->will($this->returnValue($dataSource)); - - $this->assertEquals(json_encode($result), $this->builder->toJson($storageMock, $parentName)); - } - - public function testToJsonNoParentName() - { - $this->builder = new ConfigStorageJson(); - $data = []; - $dataSource = [ - 'data' => $data, - ]; - $result = [ - 'config' => ['components' => ['name' => $data], 'globalData' => ['globalData']], - 'meta' => null, - 'data' => [], - 'dump' => ['extenders' => []], - ]; - $componentsMock = $this->getMock('Magento\Ui\Context\Configuration', ['getData'], [], '', false); - $storageMock = $this->getMock( - 'Magento\Ui\Context\ConfigurationStorage', - ['getComponentsData', 'getGlobalData', 'getMeta', 'getDataSource'], - [], - '', - false - ); - - $storageMock->expects($this->once())->method('getComponentsData')->will($this->returnValue($componentsMock)); - $componentsMock->expects($this->any())->method('getData')->willReturn($data); - - $storageMock->expects($this->once())->method('getMeta')->will($this->returnValue($result['meta'])); - $storageMock->expects($this->once())->method('getDataSource')->will($this->returnValue($dataSource)); - $storageMock->expects($this->once())->method('getGlobalData')->willReturn($result['config']); - - $this->assertEquals(json_encode($result), $this->builder->toJson($storageMock)); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/ContentType/ContentTypeFactoryTest.php b/app/code/Magento/Ui/Test/Unit/ContentType/ContentTypeFactoryTest.php deleted file mode 100644 index 3f1c82345fcdb2706a63ef4c3a42849ca16a6441..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/ContentType/ContentTypeFactoryTest.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\ContentType; - -use \Magento\Ui\ContentType\ContentTypeFactory; - -/** - * Class ContentTypeFactoryTest - */ -class ContentTypeFactoryTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var ContentTypeFactory - */ - protected $contentTypeFactory; - - /** - * @param $type - * @param @expected - * @dataProvider getDataProvider - */ - public function testGet($type, $contentRender, $expected) - { - $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface'); - $this->contentTypeFactory = new ContentTypeFactory($objectManagerMock); - $objectManagerMock->expects($this->once())->method('get')->with($expected)->willReturn($contentRender); - $this->assertInstanceOf($expected, $this->contentTypeFactory->get($type)); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testGetTypeException() - { - $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface'); - $this->contentTypeFactory = new ContentTypeFactory($objectManagerMock); - $this->contentTypeFactory->get('bad_type'); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testGetInstanceException() - { - $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface'); - $this->contentTypeFactory = new ContentTypeFactory($objectManagerMock); - $objectManagerMock->expects($this->once())->method('get')->willReturnSelf(); - $this->contentTypeFactory->get(); - } - - /** - * @return array - */ - public function getDataProvider() - { - $htmlMock = $this->getMock('Magento\Ui\ContentType\Html', [], [], '', false); - $jsonMock = $this->getMock('Magento\Ui\ContentType\Json', [], [], '', false); - $xmlMock = $this->getMock('Magento\Ui\ContentType\Xml', [], [], '', false); - return [ - ['html', $htmlMock, 'Magento\Ui\ContentType\Html'], - ['json', $jsonMock, 'Magento\Ui\ContentType\Json'], - ['xml', $xmlMock, 'Magento\Ui\ContentType\Xml'] - ]; - } -} diff --git a/app/code/Magento/Ui/Test/Unit/ContentType/HtmlTest.php b/app/code/Magento/Ui/Test/Unit/ContentType/HtmlTest.php deleted file mode 100644 index e9485bff9816cfe6704329d76202e4bf172ccf32..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/ContentType/HtmlTest.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\ContentType; - -use \Magento\Ui\ContentType\Html; - -/** - * Class HtmlTest - */ -class HtmlTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var Html - */ - protected $html; - - /** - * @var \Magento\Framework\View\FileSystem|\PHPUnit_Framework_MockObject_MockObject - */ - protected $filesystemMock; - - /** - * @var \Magento\Framework\View\TemplateEnginePool|\PHPUnit_Framework_MockObject_MockObject - */ - protected $templateEnginePoolMock; - - /** - * @var \Magento\Framework\View\Element\UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $viewInterfaceMock; - - public function setUp() - { - $this->filesystemMock = $this->getMock( - 'Magento\Framework\View\FileSystem', - ['getTemplateFileName'], - [], - '', - false - ); - $this->templateEnginePoolMock = $this->getMock( - 'Magento\Framework\View\TemplateEnginePool', - ['get'], - [], - '', - false - ); - $this->html = new Html($this->filesystemMock, $this->templateEnginePoolMock); - $this->viewInterfaceMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponentInterface' - ); - } - - public function testRender() - { - $template = 'test_template'; - $result = 'result'; - $path = 'path'; - $this->viewInterfaceMock = $this->getMockForAbstractClass( - 'Magento\Framework\View\Element\UiComponentInterface' - ); - $templateEngineMock = $this->getMockForAbstractClass('Magento\Framework\View\TemplateEngineInterface'); - - $this->templateEnginePoolMock->expects($this->once()) - ->method('get') - ->willReturn($templateEngineMock); - $this->filesystemMock->expects($this->once()) - ->method('getTemplateFileName') - ->with($template) - ->willReturn($path); - $templateEngineMock->expects($this->once()) - ->method('render') - ->with($this->viewInterfaceMock, $path) - ->willReturn($result); - - $this->assertEquals($result, $this->html->render($this->viewInterfaceMock, $template)); - } - - public function testRenderEmpty() - { - $this->assertEquals('', $this->html->render($this->viewInterfaceMock, '')); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/Context/ConfigurationStorageTest.php b/app/code/Magento/Ui/Test/Unit/Context/ConfigurationStorageTest.php deleted file mode 100644 index bd2419521963bc29c6de5cbad8069356857f06c4..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/Context/ConfigurationStorageTest.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Ui\Test\Unit\Context; - -use \Magento\Ui\Context\ConfigurationStorage; -use \Magento\Ui\Context\Configuration; -use Magento\Framework\Data\Collection as DataCollection; - -/** - * Class ConfigurationStorageTest - * @package Magento\Ui - */ -class ConfigurationStorageTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var array - */ - protected $componentStorage = []; - - /** - * @var array - */ - protected $dataStorage = []; - - /** - * @var array - */ - protected $metaStorage = []; - - /** - * @var DataCollection[] - */ - protected $collectionStorage = []; - - /** - * @var array - */ - protected $cloudDataStorage = []; - - /** - * @var ConfigurationStorage - */ - protected $configurationStorage; - - public function setUp() - { - $this->configurationStorage = new ConfigurationStorage(); - } - - public function testAddGetComponentsData() - { - $configuration = ['key' => 'value']; - $name = 'myName'; - $parentName = 'thisParentName'; - $configurationModel = new Configuration($name, $parentName, $configuration); - $this->componentStorage = [$configurationModel->getName() => $configurationModel]; - $this->configurationStorage->addComponentsData($configurationModel); - - $this->assertEquals($this->componentStorage, $this->configurationStorage->getComponentsData(null)); - $this->assertEquals(null, $this->configurationStorage->getComponentsData('someKey')); - $this->assertEquals($configurationModel, $this->configurationStorage->getComponentsData($name)); - } - - public function testRemoveComponentsData() - { - $configuration = ['key' => 'value']; - $name = 'myName'; - $parentName = 'thisParentName'; - $configurationModel = new Configuration($name, $parentName, $configuration); - $this->componentStorage = [$configurationModel->getName() => $configurationModel]; - $this->configurationStorage->addComponentsData($configurationModel); - $this->assertEquals($configurationModel, $this->configurationStorage->getComponentsData($name)); - $this->configurationStorage->removeComponentsData($configurationModel); - $this->assertEquals(null, $this->configurationStorage->getComponentsData($name)); - } - - public function testAddGetData() - { - $name = 'myName'; - $dataSource = [ - 'data' => ['key' => 'value'], - 'config' => ['key' => 'value'], - ]; - $this->configurationStorage->addDataSource($name, $dataSource); - $this->assertEquals([$name => $dataSource], $this->configurationStorage->getDataSource(null)); - $this->assertEquals(null, $this->configurationStorage->getDataSource('someKey')); - $this->assertEquals($dataSource, $this->configurationStorage->getDataSource($name)); - } - - public function testUpdateRemoveData() - { - $dataSource = [ - 'data' => ['key' => 'value'], - 'config' => ['key' => 'value'], - ]; - $key = 'myKey'; - $this->configurationStorage->addDataSource($key, $dataSource); - $this->assertEquals($dataSource, $this->configurationStorage->getDataSource($key)); - $dataSource = [ - 'data' => ['key1' => 'value1'], - 'config' => ['key1' => 'value1'], - ]; - $this->configurationStorage->updateDataSource($key, $dataSource); - $this->assertEquals($dataSource, $this->configurationStorage->getDataSource($key)); - $this->configurationStorage->removeDataSource($key); - $this->assertEquals(null, $this->configurationStorage->getDataSource($key)); - } - - public function testAddGetMeta() - { - $data = ['key' => 'value']; - $key = 'myName'; - $this->configurationStorage->addMeta($key, $data); - $this->assertEquals([$key => $data], $this->configurationStorage->getMeta(null)); - $this->assertEquals(null, $this->configurationStorage->getMeta('someKey')); - $this->assertEquals($data, $this->configurationStorage->getMeta($key)); - } - - public function testUpdateRemoveMeta() - { - $data = ['key' => 'value']; - $key = 'myKey'; - $this->configurationStorage->addMeta($key, $data); - $this->assertEquals($data, $this->configurationStorage->getMeta($key)); - $data = ['key1' => 'value1']; - $this->configurationStorage->updateMeta($key, $data); - $this->assertEquals($data, $this->configurationStorage->getMeta($key)); - $this->configurationStorage->removeMeta($key); - $this->assertEquals(null, $this->configurationStorage->getMeta($key)); - } - - public function testAddGetDataCollection() - { - $key = 'myName'; - $dataCollection = $this->getMock('Magento\Framework\Data\CollectionDataSourceInterface', [], [], '', false); - $this->configurationStorage->addDataCollection($key, $dataCollection); - - $this->assertEquals([$key => $dataCollection], $this->configurationStorage->getDataCollection(null)); - $this->assertEquals(null, $this->configurationStorage->getDataCollection('someKey')); - $this->assertEquals($dataCollection, $this->configurationStorage->getDataCollection($key)); - } - - public function testRemoveDataCollection() - { - $key = 'myName'; - $dataCollection = $this->getMock('Magento\Framework\Data\CollectionDataSourceInterface', [], [], '', false); - $update = clone $dataCollection; - $this->configurationStorage->addDataCollection($key, $dataCollection); - $this->assertEquals($dataCollection, $this->configurationStorage->getDataCollection($key)); - $this->configurationStorage->updateDataCollection($key, $update); - $this->assertEquals($update, $this->configurationStorage->getDataCollection($key)); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/Context/ConfigurationTest.php b/app/code/Magento/Ui/Test/Unit/Context/ConfigurationTest.php deleted file mode 100644 index ae2de3bb751f3f62222e4410206f00c9a34205bf..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/Context/ConfigurationTest.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Ui\Test\Unit\Context; - -use \Magento\Ui\Context\Configuration; - -class ConfigurationTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var [] - */ - protected $configuration; - - /** - * @var string - */ - protected $name; - - /** - * @var string - */ - protected $parentName; - - /** - * @var Configuration - */ - protected $configurationModel; - - public function setUp() - { - $this->configuration = ['key' => 'value']; - $this->name = 'myName'; - $this->parentName = 'thisParentName'; - $this->configurationModel = new Configuration($this->name, $this->parentName, $this->configuration); - } - - public function testGetData() - { - $this->assertEquals($this->configuration, $this->configurationModel->getData(null)); - $this->assertEquals(null, $this->configurationModel->getData('someKey')); - $this->assertEquals('value', $this->configurationModel->getData('key')); - } - - public function testAddData() - { - $this->configurationModel->addData('new_key', 'value1'); - $this->assertEquals('value1', $this->configurationModel->getData('new_key')); - } - - public function testUpdateData() - { - $this->configurationModel->addData('new_key', 'value1'); - $this->assertEquals('value1', $this->configurationModel->getData('new_key')); - $this->configurationModel->updateData('new_key', 'value2'); - $this->assertEquals('value2', $this->configurationModel->getData('new_key')); - } - - public function testGetName() - { - $this->assertEquals($this->name, $this->configurationModel->getName()); - } - - public function testGetParentName() - { - $this->assertEquals($this->parentName, $this->configurationModel->getParentName()); - } -} diff --git a/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Index/RenderTest.php b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Index/RenderTest.php index 9239d619dbb64f5ed10cb6cda9820376c1bdfcfc..f3bc80d217c4d7cdadffd44ae412aa26d777a5fe 100644 --- a/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Index/RenderTest.php +++ b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Index/RenderTest.php @@ -63,24 +63,31 @@ class RenderTest extends \PHPUnit_Framework_TestCase $this->requestMock->expects($this->at(0)) ->method('getParam') - ->with('component') - ->willReturn($name); - $this->requestMock->expects($this->at(1)) - ->method('getParam') - ->with('name') + ->with('namespace') ->willReturn($name); $this->responseMock->expects($this->once()) ->method('appendBody') ->with($renderedData); - $viewMock = $this->getMock('Magento\Ui\Form\Field', ['render'], [], '', false); + /** + * @var \Magento\Framework\View\Element\UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject $viewMock + */ + $viewMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponentInterface', + [], + '', + false, + true, + true, + ['render'] + ); $viewMock->expects($this->once()) ->method('render') ->willReturn($renderedData); $this->uiFactoryMock->expects($this->once()) - ->method('createUiComponent') + ->method('create') ->willReturn($viewMock); - $this->assertNull($this->render->execute()); + $this->render->execute(); } } diff --git a/app/code/Magento/Ui/Test/Unit/DataProvider/Config/FileResolverTest.php b/app/code/Magento/Ui/Test/Unit/DataProvider/Config/FileResolverTest.php deleted file mode 100644 index c1518f0b1a7f18b023df12ae17dc91cf3fd4ab68..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/Test/Unit/DataProvider/Config/FileResolverTest.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\Test\Unit\DataProvider\Config; - -use \Magento\Ui\DataProvider\Config\FileResolver; - -use Magento\Framework\Filesystem; - -class FileResolverTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Framework\Filesystem\Directory\Read | \PHPUnit_Framework_MockObject_MockObject - */ - private $mockDirectoryRead; - - /** - * @var FileResolver - */ - private $fileResolver; - - public function setUp() - { - $this->mockDirectoryRead = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\Read') - ->disableOriginalConstructor() - ->getMock(); - $stubFileIteratorFactory = $this->getMockBuilder('Magento\Framework\Config\FileIteratorFactory') - ->disableOriginalConstructor() - ->getMock(); - $stubFilesystem = $this->getMockBuilder('Magento\Framework\Filesystem') - ->disableOriginalConstructor() - ->getMock(); - $stubFilesystem->expects($this->any()) - ->method('getDirectoryRead') - ->willReturn($this->mockDirectoryRead); - $this->fileResolver = new FileResolver($stubFilesystem, $stubFileIteratorFactory); - } - - public function testItAppliesTheFilenamePattern() - { - $this->mockDirectoryRead->expects($this->once()) - ->method('search') - ->with($this->matchesRegularExpression('#\*\.xml$#')) - ->willReturn([]); - - $this->fileResolver->get('*.xml', ''); - } -} diff --git a/app/code/Magento/Ui/composer.json b/app/code/Magento/Ui/composer.json index ecf417cad0f81fd792b366b6d2f314848fbfcf7b..07c4a7c8ab3910486f2e7369f3f7b47d30eb6f3b 100644 --- a/app/code/Magento/Ui/composer.json +++ b/app/code/Magento/Ui/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Ui/etc/di.xml b/app/code/Magento/Ui/etc/di.xml index 55a44cd9d4df72096e6fc157f80ba2cedd56d11a..b5684f5734d9b6e641b01f26aaee55b92befa5ea 100644 --- a/app/code/Magento/Ui/etc/di.xml +++ b/app/code/Magento/Ui/etc/di.xml @@ -6,20 +6,250 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> - <preference for="Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface" type="Magento\Ui\ContentType\Builder\ConfigJson" /> - <preference for="Magento\Framework\View\Element\UiComponent\ConfigStorageBuilderInterface" type="Magento\Ui\ContentType\Builder\ConfigStorageJson" /> - <preference for="Magento\Framework\View\Element\UiComponent\ConfigInterface" type="Magento\Ui\Context\Configuration" /> - <preference for="Magento\Framework\View\Element\UiComponent\ConfigStorageInterface" type="Magento\Ui\Context\ConfigurationStorage" /> - <preference for="Magento\Ui\Component\Control\ActionPoolInterface" type="Magento\Ui\Component\Control\ActionPool" /> + <preference for="Magento\Framework\View\Element\UiComponent\ContainerInterface" type="Magento\Ui\Component\Wrapper\UiComponent" /> + <preference for="Magento\Framework\View\Element\UiComponent\Control\ActionPoolInterface" type="Magento\Ui\Component\Control\ActionPool" /> + <preference for="Magento\Framework\Data\Argument\InterpreterInterface" type="Magento\Framework\Data\Argument\Interpreter\Composite" /> + <preference for="Magento\Framework\Config\ConverterInterface" type="Magento\Framework\View\Element\UiComponent\Config\Converter" /> + <preference for="Magento\Framework\View\Element\UiComponent\Config\ManagerInterface" type="Magento\Framework\View\Element\UiComponent\Config\Manager" /> + <preference for="Magento\Framework\View\Element\UiComponent\ContextInterface" type="Magento\Framework\View\Element\UiComponent\Context" /> + <preference for="Magento\Framework\View\Element\UiComponent\LayoutInterface" type="Magento\Ui\Component\Layout\Generic"/> + <type name="Magento\Framework\View\Element\UiComponent\TemplateAdapter" shared="false" /> + <type name="Magento\Framework\View\TemplateEngineFactory"> + <arguments> + <argument name="engines" xsi:type="array"> + <item name="xhtml" xsi:type="string">Magento\Ui\TemplateEngine\Xhtml</item> + </argument> + </arguments> + </type> + <type name="Magento\Ui\TemplateEngine\Xhtml"> + <arguments> + <argument name="compiler" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler</argument> + </arguments> + </type> + <type name="Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeFactory"> + <arguments> + <argument name="types" xsi:type="array"> + <item name="html" xsi:type="string">Magento\Framework\View\Element\UiComponent\ContentType\Html</item> + <item name="json" xsi:type="string">Magento\Framework\View\Element\UiComponent\ContentType\Json</item> + <item name="xml" xsi:type="string">Magento\Framework\View\Element\UiComponent\ContentType\Xml</item> + </argument> + </arguments> + </type> + <type name="Magento\Ui\TemplateEngine\Xhtml\Compiler\Text"> + <arguments> + <argument name="directivePool" xsi:type="array"> + <item name="variable" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\Variable</item> + <item name="callableMethod" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod</item> + </argument> + </arguments> + </type> + <type name="Magento\Ui\TemplateEngine\Xhtml\Compiler\Attribute"> + <arguments> + <argument name="directivePool" xsi:type="array"> + <item name="variable" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\Variable</item> + <item name="callableMethod" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod</item> + </argument> + </arguments> + </type> + <type name="Magento\Ui\TemplateEngine\Xhtml\Compiler" shared="false"> + <arguments> + <argument name="compilerText" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Text</argument> + <argument name="compilerAttribute" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Attribute</argument> + <argument name="compilerCdata" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Cdata</argument> + <argument name="compilerComment" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Comment</argument> + <argument name="elementCompilers" xsi:type="array"> + <item name="render" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Render</item> + <item name="content" xsi:type="object">\Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Content</item> + <item name="form" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Form</item> + </argument> + </arguments> + </type> + <virtualType name="uiConfigurationDomMerger" type="Magento\Framework\View\Element\UiComponent\Config\DomMerger"> + <arguments> + <argument name="schemaFileType" xsi:type="string">etc</argument> + <argument name="schemaFileModule" xsi:type="string">Magento_Ui</argument> + <argument name="schemaFileName" xsi:type="string">ui_configuration.xsd</argument> + <argument name="contextXPath" xsi:type="array"> + <item name="ui_context" xsi:type="string">/</item> + </argument> + <argument name="idAttributes" xsi:type="array"> + <item name="attribute_name" xsi:type="string">name</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Framework\View\Element\UiComponent\Config\Manager"> + <arguments> + <argument name="domMerger" xsi:type="object">uiConfigurationDomMerger</argument> + </arguments> + </type> + <virtualType name="uiTemplateDomMerger" type="Magento\Framework\View\Element\UiComponent\Config\DomMerger"> + <arguments> + <argument name="schemaFileType" xsi:type="string">etc</argument> + <argument name="schemaFileModule" xsi:type="string">Magento_Ui</argument> + <argument name="schemaFileName" xsi:type="string">ui_template.xsd</argument> + <argument name="contextXPath" xsi:type="array"> + <item name="ui_context" xsi:type="string">/</item> + </argument> + <argument name="idAttributes" xsi:type="array"> + <item name="attribute_name" xsi:type="string">name</item> + <item name="attribute_id" xsi:type="string">id</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Framework\View\Element\UiComponent\Config\Provider\Template"> + <arguments> + <argument name="domMerger" xsi:type="object">uiTemplateDomMerger</argument> + </arguments> + </type> + <virtualType name="uiDefinitionDomMerger" type="Magento\Framework\View\Element\UiComponent\Config\DomMerger"> + <arguments> + <argument name="schemaFileType" xsi:type="string">etc</argument> + <argument name="schemaFileModule" xsi:type="string">Magento_Ui</argument> + <argument name="schemaFileName" xsi:type="string">ui_definition.xsd</argument> + <argument name="contextXPath" xsi:type="array"> + <item name="ui_context" xsi:type="string">/components</item> + </argument> + <argument name="idAttributes" xsi:type="array"> + <item name="attribute_name" xsi:type="string">name</item> + </argument> + <argument name="isMergeSimpleXMLElement" xsi:type="boolean">true</argument> + </arguments> + </virtualType> + <virtualType name="uiDefinitionFileCollector" type="Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollector"> + <arguments> + <argument name="searchPattern" xsi:type="string">etc/definition.xml</argument> + </arguments> + </virtualType> + <virtualType name="uiDefinitionReader" type="Magento\Framework\View\Element\UiComponent\Config\Reader"> + <arguments> + <argument name="fileCollector" xsi:type="object">uiDefinitionFileCollector</argument> + <argument name="domMerger" xsi:type="object">uiDefinitionDomMerger</argument> + </arguments> + </virtualType> + <type name="Magento\Framework\View\Element\UiComponent\Config\Provider\Component\Definition"> + <arguments> + <argument name="uiReader" xsi:type="object">uiDefinitionReader</argument> + </arguments> + </type> <type name="Magento\Ui\Component\Filter\FilterPool"> <arguments> <argument name="filters" xsi:type="array"> <item name="filter_input" xsi:type="string">Magento\Ui\Component\Filter\Type\Input</item> <item name="filter_select" xsi:type="string">Magento\Ui\Component\Filter\Type\Select</item> <item name="filter_range" xsi:type="string">Magento\Ui\Component\Filter\Type\Range</item> - <item name="filter_date" xsi:type="string">Magento\Ui\Component\Filter\Type\Date</item> <item name="filter_store" xsi:type="string">Magento\Ui\Component\Filter\Type\Store</item> </argument> </arguments> </type> + <type name="Magento\Ui\Component\Layout\LayoutPool"> + <arguments> + <argument name="types" xsi:type="array"> + <item name="generic" xsi:type="array"> + <item name="class" xsi:type="string">Magento\Ui\Component\Layout\Generic</item> + <item name="template" xsi:type="string">templates/layout/generic</item> + </item> + <item name="tabs" xsi:type="array"> + <item name="class" xsi:type="string">Magento\Ui\Component\Layout\Tabs</item> + <item name="template" xsi:type="string">templates/layout/tabs</item> + </item> + </argument> + </arguments> + </type> + <virtualType name="arrayArgumentInterpreterProxy" type="Magento\Framework\Data\Argument\InterpreterInterface\Proxy"> + <arguments> + <argument name="instanceName" xsi:type="string">Magento\Framework\Data\Argument\Interpreter\ArrayType</argument> + </arguments> + </virtualType> + <virtualType name="configurableObjectArgumentInterpreterProxy" type="Magento\Framework\Data\Argument\InterpreterInterface\Proxy"> + <arguments> + <argument name="instanceName" xsi:type="string">Magento\Framework\View\Element\UiComponent\Argument\Interpreter\ConfigurableObject</argument> + </arguments> + </virtualType> + <type name="Magento\Framework\Data\Argument\Interpreter\Composite"> + <arguments> + <argument name="interpreters" xsi:type="array"> + <item name="object" xsi:type="object">Magento\Framework\Data\Argument\Interpreter\Object</item> + <item name="configurableObject" xsi:type="object">configurableObjectArgumentInterpreterProxy</item> + <item name="array" xsi:type="object">arrayArgumentInterpreterProxy</item> + <item name="boolean" xsi:type="object">Magento\Framework\Data\Argument\Interpreter\Boolean</item> + <item name="number" xsi:type="object">Magento\Framework\Data\Argument\Interpreter\Number</item> + <item name="string" xsi:type="object">Magento\Framework\Data\Argument\Interpreter\String</item> + <item name="null" xsi:type="object">Magento\Framework\Data\Argument\Interpreter\NullType</item> + </argument> + <argument name="discriminator" xsi:type="string">xsi:type</argument> + </arguments> + </type> + <type name="Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollector"> + <arguments> + <argument name="collectorAggregated" xsi:type="object">uiComponentAggregatedCollector</argument> + </arguments> + </type> + <virtualType name="uiComponentAggregatedCollector" type="Magento\Framework\View\Layout\File\Collector\Aggregated"> + <arguments> + <argument name="baseFiles" xsi:type="object">uiComponentAggregatedSourceBaseSorted</argument> + <argument name="themeFiles" xsi:type="object">uiComponentAggregatedSourceThemeSorted</argument> + <argument name="overrideBaseFiles" xsi:type="object">uiComponentAggregatedSourceOverrideBaseSorted</argument> + <argument name="overrideThemeFiles" xsi:type="object">uiComponentAggregatedSourceOverrideThemeSorted</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceBase" type="Magento\Framework\View\File\Collector\Base"> + <arguments> + <argument name="subDir" xsi:type="string">ui_component</argument> + </arguments> + </virtualType> + <virtualType shared="false" name="uiComponentAggregatedSourceBaseFiltered" type="Magento\Framework\View\File\Collector\Decorator\ModuleOutput"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceBase</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceBaseSorted" type="Magento\Framework\View\File\Collector\Decorator\ModuleDependency"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceBaseFiltered</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceTheme" type="Magento\Framework\View\File\Collector\ThemeModular"> + <arguments> + <argument name="subDir" xsi:type="string">ui_component</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceThemeFiltered" type="Magento\Framework\View\File\Collector\Decorator\ModuleOutput"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceTheme</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceThemeSorted" type="Magento\Framework\View\File\Collector\Decorator\ModuleDependency"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceThemeFiltered</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceOverrideBase" type="Magento\Framework\View\File\Collector\Override\Base"> + <arguments> + <argument name="subDir" xsi:type="string">layout/override/base</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceOverrideBaseFiltered" type="Magento\Framework\View\File\Collector\Decorator\ModuleOutput"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceOverrideBase</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceOverrideBaseSorted" type="Magento\Framework\View\File\Collector\Decorator\ModuleDependency"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceOverrideBaseFiltered</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceOverrideTheme" type="Magento\Framework\View\File\Collector\Override\ThemeModular"> + <arguments> + <argument name="subDir" xsi:type="string">layout/override/theme</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceOverrideThemeFiltered" type="Magento\Framework\View\File\Collector\Decorator\ModuleOutput"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceOverrideTheme</argument> + </arguments> + </virtualType> + <virtualType name="uiComponentAggregatedSourceOverrideThemeSorted" type="Magento\Framework\View\File\Collector\Decorator\ModuleDependency"> + <arguments> + <argument name="subject" xsi:type="object">uiComponentAggregatedSourceOverrideThemeFiltered</argument> + </arguments> + </virtualType> </config> diff --git a/app/code/Magento/Ui/etc/ui_components.xsd b/app/code/Magento/Ui/etc/ui_components.xsd new file mode 100644 index 0000000000000000000000000000000000000000..6cd0edbfc363f24af6de5d73fb43ab467ac69737 --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_components.xsd @@ -0,0 +1,322 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <!-- Include section --> + <xs:include schemaLocation="../../../../../lib/internal/Magento/Framework/Data/etc/argument/types.xsd"/> + <!-- Defined the types of components --> + <xs:complexType name="layout" xml:base="ui_element"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="tab"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="columns"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="column"> + <xs:complexContent> + <xs:extension base="field"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataSource"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="listing"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + <xs:attribute name="sorting" use="optional"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="true"/> + <xs:enumeration value="false"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="paging"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="filters"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="filterSelect"> + <xs:complexContent> + <xs:extension base="select"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="filterRange"> + <xs:complexContent> + <xs:extension base="input"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="filterInput"> + <xs:complexContent> + <xs:extension base="input"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="filterDate"> + <xs:complexContent> + <xs:extension base="input"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="container"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="massaction"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="form"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="input"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + <xs:attribute name="displayZone" use="optional"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="header"/> + <xs:enumeration value="content"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="checkbox"> + <xs:complexContent> + <xs:extension base="input"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="select"> + <xs:complexContent> + <xs:extension base="input"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="multiselect"> + <xs:complexContent> + <xs:extension base="select"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="textarea"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="fieldset"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="field" type="field" /> + <xs:element name="container" type="container" /> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="field"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataTypeText"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataTypeBoolean"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataTypeNumber"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataTypePrice"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataTypeMedia"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataTypeDate"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="dataTypeEmail"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="nav"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="actions"> + <xs:complexContent> + <xs:extension base="ui_element"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="configurable"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <!-- Global groups --> + <xs:group name="configurable"> + <xs:sequence> + <xs:element type="argumentType" name="argument" minOccurs="0" maxOccurs="unbounded"> + <xs:key name="configurableArgumentItemName"> + <xs:selector xpath="item"/> + <xs:field xpath="@name"/> + </xs:key> + </xs:element> + </xs:sequence> + </xs:group> + <!-- Global types --> + <xs:complexType name="constant"> + <xs:complexContent> + <xs:extension base="argumentType"/> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="ui_element"> + <xs:attribute type="xs:string" name="name" use="optional"/> + <xs:attribute type="xs:boolean" name="disabled" use="optional"/> + <xs:attribute type="xs:string" name="layout" use="optional"/> + <xs:attribute type="xs:string" name="dataSource" use="optional"/> + <xs:attribute type="xs:string" name="class" use="optional"/> + </xs:complexType> + <!-- Simple types --> + <xs:simpleType name="referenceAttributeType"> + <xs:annotation> + <xs:documentation>The value should only be {[a-z_-]+} since it is used as a reference to a database field.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:pattern value="[a-z_-]+" /> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="textAttributeType"> + <xs:annotation> + <xs:documentation>Any text value</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:pattern value="[A-Za-z0-9,_.\\: -]+" /> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/app/code/Magento/Ui/etc/ui_configuration.xsd b/app/code/Magento/Ui/etc/ui_configuration.xsd new file mode 100644 index 0000000000000000000000000000000000000000..84f16e2db35d60bc40b48e4eeeb4b45c58ff59ca --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_configuration.xsd @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <xs:annotation> + <xs:appinfo>The definition of a configuration item components</xs:appinfo> + <xs:documentation>The definition of a configuration item components</xs:documentation> + </xs:annotation> + <!-- Include section --> + <xs:include schemaLocation="ui_components.xsd"/> + <!-- Components list --> + <xs:element type="formConfiguration" name="form"/> + <xs:element type="listingConfiguration" name="listing"/> + <!-- Custom configuration --> + <xs:complexType name="containerConfiguration"> + <xs:complexContent> + <xs:extension base="container"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="paging" name="paging"/> + <xs:element type="filtersConfiguration" name="filters"/> + <xs:element type="massaction" name="massaction"/> + <xs:element type="columnsConfiguration" name="columns"/> + <xs:element type="containerConfiguration" name="container"/> + <xs:element name="field" type="field" /> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="fieldsetConfiguration"> + <xs:complexContent> + <xs:extension base="container"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="containerConfiguration" name="container"/> + <xs:element name="field" type="field" /> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="listingConfiguration"> + <xs:complexContent> + <xs:extension base="listing"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="paging" name="paging"/> + <xs:element type="filtersConfiguration" name="filters"/> + <xs:element type="massaction" name="massaction"/> + <xs:element type="dataSource" name="dataSource"/> + <xs:element type="columnsConfiguration" name="columns"/> + <xs:element type="containerConfiguration" name="container"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="formConfiguration"> + <xs:complexContent> + <xs:extension base="form"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="fieldset" type="fieldsetConfiguration" /> + <xs:element name="field" type="field" /> + <xs:element type="dataSource" name="dataSource"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="columnsConfiguration"> + <xs:complexContent> + <xs:extension base="columns"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="column" type="column" /> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="filtersConfiguration"> + <xs:complexContent> + <xs:extension base="filters"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="filterDate" type="filterDate" /> + <xs:element name="filterInput" type="filterInput" /> + <xs:element name="filterRange" type="filterRangeConfiguration" /> + <xs:element name="filterSelect" type="filterSelect" /> + <xs:element name="containerConfiguration" type="container" /> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="filterRangeConfiguration"> + <xs:complexContent> + <xs:extension base="filterRange"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="filterDate" type="filterDate" /> + <xs:element name="filterInput" type="filterInput" /> + <xs:element name="filterSelect" type="filterSelect" /> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> +</xs:schema> diff --git a/app/code/Magento/Ui/etc/ui_definition.xsd b/app/code/Magento/Ui/etc/ui_definition.xsd new file mode 100644 index 0000000000000000000000000000000000000000..fc279745827db502f0c3504c96a8e521ec102dc3 --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_definition.xsd @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <!-- Include section --> + <xs:include schemaLocation="ui_components.xsd"/> + <!-- Definition the document element --> + <xs:element name="components" type="definition"/> + <!-- Registering components in the system --> + <xs:complexType name="definition"> + <xs:annotation> + <xs:appinfo>Registering components in the system and basic setup</xs:appinfo> + <xs:documentation>Registering components in the system and basic setup</xs:documentation> + </xs:annotation> + <xs:all> + <!-- Components list --> + <xs:element type="tab" name="tab"/> + <xs:element type="dataSource" name="dataSource"/> + <xs:element type="paging" name="paging"/> + <xs:element type="massaction" name="massaction"/> + <xs:element type="listingDefinition" name="listing"/> + <xs:element type="formDefinition" name="form"/> + <xs:element type="fieldset" name="fieldset"/> + <xs:element type="field" name="field"/> + <xs:element type="filters" name="filters"/> + <xs:element type="columns" name="columns"/> + <xs:element type="column" name="column"/> + <xs:element type="filterSelect" name="filterSelect"/> + <xs:element type="filterRange" name="filterRange"/> + <xs:element type="filterInput" name="filterInput"/> + <xs:element type="filterDate" name="filterDate"/> + <xs:element type="container" name="container"/> + <xs:element type="input" name="input"/> + <xs:element type="checkbox" name="checkbox"/> + <xs:element type="select" name="select"/> + <xs:element type="multiselect" name="multiselect"/> + <xs:element type="textarea" name="textarea"/> + <xs:element type="dataTypeText" name="text"/> + <xs:element type="dataTypeBoolean" name="boolean"/> + <xs:element type="dataTypeNumber" name="number"/> + <xs:element type="dataTypePrice" name="price"/> + <xs:element type="dataTypeMedia" name="media"/> + <xs:element type="dataTypeDate" name="date"/> + <xs:element type="dataTypeEmail" name="email"/> + <xs:element type="nav" name="nav"/> + <xs:element type="actions" name="actions"/> + </xs:all> + </xs:complexType> + <!-- Custom configuration --> + <xs:complexType name="listingDefinition"> + <xs:complexContent> + <xs:extension base="listing"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="dataSource" name="dataSource"/> + <xs:element type="paging" name="paging"/> + <xs:element type="massaction" name="massaction"/> + <xs:element type="columns" name="columns"/> + <xs:element type="filters" name="filters"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="formDefinition"> + <xs:complexContent> + <xs:extension base="form"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="fieldset" name="fieldset"/> + <xs:element type="dataSource" name="dataSource"/> + </xs:choice> + </xs:extension> + </xs:complexContent> + </xs:complexType> +</xs:schema> diff --git a/app/code/Magento/Ui/etc/ui_template.xsd b/app/code/Magento/Ui/etc/ui_template.xsd new file mode 100644 index 0000000000000000000000000000000000000000..ef5b731067363469152765f0a5579edb76e129d6 --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_template.xsd @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <xs:element name="form"> + <xs:complexType > + <xs:sequence> + <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="div" > + <xs:complexType > + <xs:sequence> + <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" /> + </xs:sequence> + <xs:anyAttribute processContents="lax" /> + </xs:complexType> + </xs:element> +</xs:schema> diff --git a/app/code/Magento/Ui/view/base/layout/ui_components.xml b/app/code/Magento/Ui/view/base/layout/ui_components.xml deleted file mode 100644 index d8d2be00aa0e54a757831b1d04d749dca4a29ae1..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/layout/ui_components.xml +++ /dev/null @@ -1,245 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/layout_generic.xsd"> - <block class="Magento\Ui\Component\Listing" name="listing"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::listing/horizontal_grid.phtml</argument> - <argument name="save_parameters_in_session" xsi:type="string">1</argument> - <argument name="client_root" xsi:type="string">mui/index/render</argument> - </arguments> - <container label="Listing Head" name="listing_head"/> - <container label="Listing Before" name="listing_before"> - <ui_component name="sorting" component="component_sorting" /> - <ui_component name="paging" component="component_paging" /> - <ui_component name="filters" component="component_filter_pool" /> - <ui_component name="massactions" component="component_control_massaction" /> - </container> - </block> - <block class="Magento\Ui\Component\Paging" name="component_paging"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::paging/default.phtml</argument> - </arguments> - </block> - <block class="Magento\Ui\Component\FilterPool" name="component_filter_pool"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::filter_pool/default.phtml</argument> - <argument name="config" xsi:type="array"> - <item name="types" xsi:type="array"> - <item name="filter_date" xsi:type="array"> - <item name="dateFormat" xsi:type="string">mm/dd/yyyy</item> - </item> - <item name="filter_input" xsi:type="array"/> - <item name="filter_select" xsi:type="array"/> - <item name="filter_range" xsi:type="array"/> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Filter\Type\Select" name="filter_select" /> - <block class="Magento\Ui\Component\Filter\Type\Range" name="filter_range" /> - <block class="Magento\Ui\Component\Filter\Type\Input" name="filter_input" /> - <block class="Magento\Ui\Component\Filter\Type\Date" name="filter_date" /> - - <block class="Magento\Ui\Component\Sorting" name="component_sorting"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::sorting/default.phtml</argument> - <argument name="config" xsi:type="array"> - <item name="direction" xsi:type="string">asc</item> - </argument> - </arguments> - </block> - - <block class="Magento\Ui\Component\MassAction" name="component_control_massaction"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::listingcontainer/massaction/default.phtml</argument> - </arguments> - </block> - - <block class="Magento\Ui\Component\Control\Action" name="actions" /> - - <block class="Magento\Ui\Component\Form\Element\Input" name="input"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">input</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\Input" name="checkbox"> - <arguments> - <argument name="input_type" xsi:type="string">checkbox</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/boolean</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">checkbox</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\Select" name="select"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/select</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">select</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\Select" name="multiselect"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/multiselect</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">multiselect</item> - <item name="template" xsi:type="string">ui/form/element/multiselect</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\Textarea" name="textarea"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/textarea</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">textarea</item> - </item> - </argument> - </arguments> - </block> - - <block class="Magento\Ui\Component\Form\Element\DataType\Text" name="text" /> - <block class="Magento\Ui\Component\Form\Element\DataType\Number" name="number" /> - <block class="Magento\Ui\Component\Form\Element\DataType\Price" name="price" /> - <block class="Magento\Ui\Component\Form\Element\DataType\Media" name="media"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="extends" xsi:type="string">input</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">media</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\DataType\Date" name="date"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="extends" xsi:type="string">input</item> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/date</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">date</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\DataType\Boolean" name="boolean"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="extends" xsi:type="string">input</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">select</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Element\DataType\Email" name="email"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="extends" xsi:type="string">input</item> - <item name="config" xsi:type="array"> - <item name="input_type" xsi:type="string">email</item> - </item> - </argument> - </arguments> - </block> - - <block class="Magento\Ui\Component\Form" name="form"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::form/default.phtml</argument> - <argument name="save_url" xsi:type="string">mui/form/save</argument> - <argument name="validate_url" xsi:type="string">mui/form/validate</argument> - <argument name="layout" xsi:type="array"> - <item name="type" xsi:type="string">tabs</item> - </argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form</item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Form\Fieldset" name="fieldset"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::form/fieldset/default.phtml</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/components/fieldset</item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Layout\Tabs" name="tabs"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::layout/tabs/default.phtml</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/components/tabs</item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Layout\Tabs\Tab" name="tab"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::layout/tabs/tab/default.phtml</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/components/area</item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Layout\Group" name="group"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::layout/group/default.phtml</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/components/group</item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Layout\Tabs\Nav" name="nav"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::layout/tabs/nav/default.phtml</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/components/tab_group</item> - <item name="config" xsi:type="array"> - <item name="template" xsi:type="string">ui/tab</item> - </item> - </argument> - </arguments> - </block> - <block class="Magento\Ui\Component\Container\Content" name="html_content"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::container/content/default.phtml</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/components/html</item> - </argument> - </arguments> - </block> - - <block class="Magento\Ui\Component\Form\Collection" name="collection"> - <arguments> - <argument name="content_template" xsi:type="string">Magento_Ui::form/collection/default.phtml</argument> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/components/collection</item> - </argument> - </arguments> - </block> - - <block class="Magento\Ui\Component\Form\Element\Input" name="post_code"> - <arguments> - <argument name="js_config" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item> - <item name="dependentFiled" xsi:type="string">country_id</item> - </argument> - </arguments> - </block> -</layout> diff --git a/app/code/Magento/Ui/view/base/requirejs-config.js b/app/code/Magento/Ui/view/base/requirejs-config.js index 8f1227f8bf26407d0418aeecfead532701ba900c..50196fbadd38064a068d4850c11b6da7e74e31ad 100644 --- a/app/code/Magento/Ui/view/base/requirejs-config.js +++ b/app/code/Magento/Ui/view/base/requirejs-config.js @@ -7,5 +7,11 @@ var config = { paths: { 'ui/template': 'Magento_Ui/templates', 'i18n': 'Magento_Ui/js/lib/i18n' + }, + map: { + '*': { + uiComponent: 'Magento_Ui/js/lib/component/main', + uiRegistry: 'Magento_Ui/js/lib/registry/registry' + } } }; \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/templates/context/default.phtml b/app/code/Magento/Ui/view/base/templates/context/default.phtml index ecd62351fb8d098b71c2dc9a6c611893be33c01d..e05848ba175c40b7cc3e95ef5e37472730bd3a96 100644 --- a/app/code/Magento/Ui/view/base/templates/context/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/context/default.phtml @@ -3,10 +3,5 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/** - * @var \Magento\Ui\Context\DataProvider $block - */ ?> -<script type="application/json"> - <?php echo $block->getAsJson(); ?> -</script> +<script data-mage-init='{ "Magento_Ui/js/core/app": "" }' type="application/json"></script> diff --git a/app/code/Magento/Ui/view/base/templates/filter_pool/active.phtml b/app/code/Magento/Ui/view/base/templates/filter_pool/active.phtml deleted file mode 100644 index f4419a7023e503893ffa2d07219e20f1900997d2..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/filter_pool/active.phtml +++ /dev/null @@ -1,15 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @var \Magento\Ui\Component\Filter $block - */ -?> -<strong class="item-label" data-bind-="text: $t(filter.title)"><?php echo $block->getData('label') ?></strong> -<span class="item-value" data-bind-="text: $t(filter.output)"><?php echo $block->getData('current_display_value') ?></span> -<button data-bind-="click: $parent.onClear(filter)" type="button" class="action action-remove"><span data-bind-="text: $t('Remove')"></span></button> diff --git a/app/code/Magento/Ui/view/base/templates/filter_pool/default.phtml b/app/code/Magento/Ui/view/base/templates/filter_pool/default.phtml deleted file mode 100644 index caec2660f677e5534558308e33021b753a8639e6..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/filter_pool/default.phtml +++ /dev/null @@ -1,19 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/** - * @var \Magento\Ui\Component\FilterPool $block - */ -?> -<script type="text/x-magento-init"> - { - "*": { - "Magento_Ui/js/listing/filter": <?php echo $block->getConfigBuilder()->toJson($block->getConfig()); ?> - } - } -</script> -<div data-bind="scope: '<?php echo $block->getParentName(); ?>:<?php echo $block->getName(); ?>'"> - <!-- ko template: 'ui/filter' --><!-- /ko --> -</div> diff --git a/app/code/Magento/Ui/view/base/templates/form/default.phtml b/app/code/Magento/Ui/view/base/templates/form/default.phtml index 7c51b5cb65711b8067c4abc21e1ee53d6f738754..3f42ae43172860c4eb6769bf949c7255f97e2dc6 100644 --- a/app/code/Magento/Ui/view/base/templates/form/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/form/default.phtml @@ -6,20 +6,13 @@ /** * @var \Magento\Ui\Component\Form $block */ -$formConfig = $block->getRenderContext()->getConfigBuilder()->toJsonNew($block->getRenderContext()->getStorage()); +echo $block->renderChildComponent('before_form'); ?> -<script type="text/x-magento-init"> - { - "*": { - "Magento_Ui/js/core/app": <?php echo $formConfig; ?> - } - } -</script> -<div data-role="spinner" data-component="<?php echo $block->getDataScope(); ?>.areas" class="grid-loading-mask"> - <div class="spinner"> - <span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span> - </div> +<div data-role="spinner" data-component="<?php echo $block->getName(); ?>.areas" class="admin__data-grid-loading-mask"> + <div class="grid-loader"></div> </div> -<div data-bind="scope: '<?php echo $block->getDataScope(); ?>.areas'"> +<div data-bind="scope: '<?php echo $block->getName(); ?>.areas'" class="entry-edit form-inline"> <!-- ko template: getTemplate() --><!-- /ko --> </div> +<?php +echo $block->renderChildComponent('after_form'); diff --git a/app/code/Magento/Ui/view/base/templates/form/fieldset/default.phtml b/app/code/Magento/Ui/view/base/templates/form/fieldset/default.phtml deleted file mode 100644 index 0d814d882b5f9ca4524523847e639d1680bf7516..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/form/fieldset/default.phtml +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @var \Magento\Ui\Component\Form\Fieldset $block - */ -$children = $block->getChildren(); -$content = $block->getContent(); -$ajaxUrl = $block->getAjaxUrl(); -?> -<div class="admin__fieldset-wrapper-title" tabindex="3" data-bind="click: onClick, keyboard: { 13: toggle }"> - <strong class="title"> - <span data-bind="text: label"><?php echo $block->getData('config/label'); ?></span> - </strong> -</div> - -<div class="admin__fieldset-wrapper-content"> - <fieldset id="<?php echo $block->getData('index'); ?>" class="admin__fieldset"> - <?php if (!empty($content)): ?> - <?php echo $content; ?> - <?php endif; ?> - <?php if (is_array($children) && !$ajaxUrl): ?> - <?php foreach ($children as $childName): ?> - <?php $childElement = $block->getLayoutElement($childName);?> - <p><?php echo $block->renderElement('group', $childElement); ?></p> - <?php endforeach; ?> - <?php endif; ?> - </fieldset> -</div> diff --git a/app/code/Magento/Ui/view/base/templates/label/default.phtml b/app/code/Magento/Ui/view/base/templates/label/default.phtml index b1cf43ddc16f714217fc24f76de9a8920d0fd27e..d9937521b97202e4c3358982b6f31661cc89a959 100644 --- a/app/code/Magento/Ui/view/base/templates/label/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/label/default.phtml @@ -3,9 +3,6 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/** - * @var \Magento\Ui\Component\AbstractView $block - */ ?> <span> <?php echo $block->getData('label'); ?> diff --git a/app/code/Magento/Ui/view/base/templates/layout/group/default.phtml b/app/code/Magento/Ui/view/base/templates/layout/group/default.phtml deleted file mode 100644 index c3a67828419eda7d3fd5465d6b45acd1181dd23f..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/layout/group/default.phtml +++ /dev/null @@ -1,25 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @var \Magento\Ui\Component\Layout\Group $block - */ - -?> -<div class="admin__field <?php echo $block->getIsRequired()?>" data-bind="css: {'required': required}"> - <label class="admin__field-label" data-bind="attr: { for: <?php echo $block->getData('index')?> }" for="R1WKK"> - <span data-bind="text: element.label"><?php echo $block->getData('label')?></span> - </label> - <div class="admin__field-control"> - <?php if ($block->getChildren()): ?> - <?php foreach ($block->getChildren() as $child): ?> - <?php echo $block->renderElement($child['dataType'], ['field_config' => $child]); ?> - <?php endforeach; ?> - <?php endif;?> - </div> -</div> diff --git a/app/code/Magento/Ui/view/base/templates/layout/tabs/nav/default.phtml b/app/code/Magento/Ui/view/base/templates/layout/tabs/nav/default.phtml index 46f9c9a8f0ec5672b8b8bed3a9b48fefa7d58bf6..471cf5f85bb6c48b670f61871040913c100a4ded 100644 --- a/app/code/Magento/Ui/view/base/templates/layout/tabs/nav/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/layout/tabs/nav/default.phtml @@ -7,11 +7,6 @@ * @var \Magento\Ui\Component\Layout\Tabs\Nav $block */ ?> -<div data-role="spinner" data-component="<?php echo $block->getDataScope(); ?>.sections" class="grid-loading-mask"> - <div class="spinner"> - <span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span> - </div> -</div> <div data-bind="scope: '<?php echo $block->getDataScope(); ?>.sections' " class="ui-tabs"> <!-- ko template: getTemplate() --><!-- /ko --> </div> diff --git a/app/code/Magento/Ui/view/base/templates/listing/horizontal_grid.phtml b/app/code/Magento/Ui/view/base/templates/listing/horizontal_grid.phtml deleted file mode 100644 index 32f2356edd984294bd88fc9387e1a8bf7376aee6..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/listing/horizontal_grid.phtml +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -?> -<?php -/** - * @var \Magento\Ui\Component\Listing $block - */ -?> -<script type="text/x-magento-init"> -{ - "*": { - "Magento_Ui/js/lib/provider": - <?php echo $block->getRenderContext() - ->getConfigBuilder() - ->toJson($block->getRenderContext()->getStorage(), $block->getName()); - ?>, - "Magento_Ui/js/listing/grid": <?php echo $block->getConfigBuilder()->toJson($block->getConfig()); ?> - } -} -</script> -<?php echo $block->getChildHtml('listing_head'); ?> -<div class="grid"> - <?php echo $block->getChildHtml('listing_before'); ?> - <div data-bind="scope: '<?php echo $block->getParentName(); ?>:<?php echo $block->getName(); ?>'"> - <!-- ko template: getTemplate() --><!-- /ko --> - </div> - <?php echo $block->getChildHtml('listing_after'); ?> -</div> -<div data-role="spinner" class="grid-loading-mask"> - <div class="grid-loader"></div> -</div> diff --git a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/default.phtml b/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/default.phtml deleted file mode 100644 index f0e80904214fb86fad22be517b94e6ef1643b362..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/default.phtml +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -?> -<?php -/** - * @var \Magento\Ui\Component\MassAction $block - */ -?> -<script type="text/x-magento-init"> - { - "*": { - "Magento_Ui/js/listing/massaction": <?php echo $block->getConfigBuilder()->toJson($block->getConfig()); ?> - } - } -</script> -<div data-bind="scope: '<?php echo $block->getParentName(); ?>:<?php echo $block->getName(); ?>'" class="grid-actions"> - <!-- ko template: 'ui/massaction' --><!-- /ko --> -</div> diff --git a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/page_actions.phtml b/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/page_actions.phtml deleted file mode 100644 index 1bba18bb5ff432a80fd15a98edb53ae1cbed53a3..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/page_actions.phtml +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -?> -<?php -/** - * @var \Magento\Ui\Component\MassAction $block - */ -?> -<script type="text/x-magento-init"> - { - "*": { - "Magento_Ui/js/listing/massaction": <?php echo $block->getConfigBuilder()->toJson($block->getConfig()); ?> - } - } -</script> -<div data-bind="scope: '<?php echo $block->getParentName(); ?>:<?php echo $block->getName(); ?>'"> - <!-- ko template: 'ui/pageactions' --><!-- /ko --> -</div> diff --git a/app/code/Magento/Ui/view/base/templates/paging/default.phtml b/app/code/Magento/Ui/view/base/templates/paging/default.phtml deleted file mode 100644 index 6c710bdf1b15441e91ba811da8951d3166919276..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/paging/default.phtml +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -?> -<?php -/** - * @var \Magento\Ui\Component\Paging $block - */ -?> -<script type="text/x-magento-init"> - { - "*": { - "Magento_Ui/js/listing/paging": <?php echo $block->getConfigBuilder()->toJson($block->getConfig()); ?> - } - } -</script> -<div data-bind="scope: '<?php echo $block->getParentName(); ?>:<?php echo $block->getName(); ?>'" class="pager"> - <!-- ko template: 'ui/pagination' --><!-- /ko --> -</div> diff --git a/app/code/Magento/Ui/view/base/templates/sorting/default.phtml b/app/code/Magento/Ui/view/base/templates/sorting/default.phtml deleted file mode 100644 index 1b85352c82b4ee8da9e30b2847869a48d187c84a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/templates/sorting/default.phtml +++ /dev/null @@ -1,19 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -?> -<?php -/** - * @var \Magento\Ui\Component\Sorting $block - */ - -?> -<script type="text/x-magento-init"> - { - "*": { - "Magento_Ui/js/listing/sorting": <?php echo $block->getConfigBuilder()->toJson($block->getConfig()); ?> - } - } -</script> diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml new file mode 100644 index 0000000000000000000000000000000000000000..4ebc69d2284abb3514c412081e36b0225781eb0e --- /dev/null +++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml @@ -0,0 +1,225 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<components xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../etc/ui_definition.xsd"> + <dataSource class="Magento\Ui\Component\DataSource"/> + <listing sorting="true" class="Magento\Ui\Component\Listing"> + <argument name="data" xsi:type="array"> + <item name="template" xsi:type="string">templates/listing/default</item> + <item name="save_parameters_in_session" xsi:type="string">1</item> + <item name="client_root" xsi:type="string">mui/index/render</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + </item> + </argument> + </listing> + <paging class="Magento\Ui\Component\Paging"> + <argument name="data" xsi:type="array"> + <item name="template" xsi:type="string">templates/paging/default</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/paging</item> + </item> + </argument> + </paging> + <filters class="Magento\Ui\Component\Filters"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/filters/filters</item> + </item> + </argument> + </filters> + <filterSelect class="Magento\Ui\Component\Filters\Type\Select"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string" translate="true">ui/grid/filters/elements/select</item> + </item> + </argument> + </filterSelect> + <filterRange class="Magento\Ui\Component\Filters\Type\Range"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/filters/group</item> + </item> + </argument> + </filterRange> + <filterInput class="Magento\Ui\Component\Filters\Type\Input"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">ui/grid/filters/elements/input</item> + </item> + </argument> + </filterInput> + <filterDate class="Magento\Ui\Component\Filters\Type\Date"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">ui/grid/filters/elements/date</item> + </item> + </argument> + </filterDate> + <container class="Magento\Ui\Component\Container"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + </item> + </argument> + </container> + <massaction class="Magento\Ui\Component\MassAction"> + <argument name="data" xsi:type="array"> + <item name="template" xsi:type="string">templates/listingcontainer/massaction/default</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/massactions</item> + </item> + </argument> + </massaction> + <actions class="Magento\Ui\Component\Control\Action"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/actions</item> + </item> + </argument> + </actions> + <input class="Magento\Ui\Component\Form\Element\Input"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">ui/form/field</item> + <item name="elementTmpl" xsi:type="string">ui/form/element/input</item> + </item> + </item> + </argument> + </input> + <checkbox class="Magento\Ui\Component\Form\Element\Checkbox"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/boolean</item> + <item name="config" xsi:type="array"> + <item name="elementTmpl" xsi:type="string">ui/form/element/checkbox</item> + </item> + </item> + </argument> + </checkbox> + <select class="Magento\Ui\Component\Form\Element\Select"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/select</item> + <item name="config" xsi:type="array"> + <item name="elementTmpl" xsi:type="string">ui/form/element/select</item> + </item> + </item> + </argument> + </select> + <multiselect class="Magento\Ui\Component\Form\Element\Select"> + <argument name="data" xsi:type="array"> + <item name="template" xsi:type="string">ui/form/element/multiselect</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/multiselect</item> + <item name="config" xsi:type="array"> + <item name="elementTmpl" xsi:type="string">ui/form/element/multiselect</item> + </item> + </item> + </argument> + </multiselect> + <textarea class="Magento\Ui\Component\Form\Element\Textarea"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/textarea</item> + <item name="config" xsi:type="array"> + <item name="elementTmpl" xsi:type="string">ui/form/element/textarea</item> + </item> + </item> + </argument> + </textarea> + <text class="Magento\Ui\Component\Form\Element\DataType\Text"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/text</item> + </item> + </argument> + </text> + <number class="Magento\Ui\Component\Form\Element\DataType\Number"/> + <price class="Magento\Ui\Component\Form\Element\DataType\Price"/> + <media class="Magento\Ui\Component\Form\Element\DataType\Media"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="extends" xsi:type="string">input</item> + </item> + </argument> + </media> + <date class="Magento\Ui\Component\Form\Element\DataType\Date"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="extends" xsi:type="string">input</item> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/date</item> + <item name="config" xsi:type="array"> + <item name="elementTmpl" xsi:type="string">ui/form/element/date</item> + </item> + </item> + </argument> + </date> + <boolean class="Magento\Ui\Component\Form\Element\DataType\Boolean"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="extends" xsi:type="string">input</item> + </item> + </argument> + </boolean> + <email class="Magento\Ui\Component\Form\Element\DataType\Email"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="extends" xsi:type="string">input</item> + <item name="config" xsi:type="array"> + <item name="elementTmpl" xsi:type="string">ui/form/element/email</item> + </item> + </item> + <item name="config" xsi:type="array"> + <item name="addbefore" xsi:type="string">@email:</item> + </item> + </argument> + </email> + <columns class="Magento\Ui\Component\Listing\Columns"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/listing</item> + </item> + </argument> + </columns> + <column class="Magento\Ui\Component\Listing\Columns\Column"/> + <form class="Magento\Ui\Component\Form"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/form</item> + </item> + <item name="template" xsi:type="string">templates/form/default</item> + </argument> + </form> + <fieldset class="Magento\Ui\Component\Form\Fieldset"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/components/fieldset</item> + </item> + </argument> + </fieldset> + <field class="Magento\Ui\Component\Form\Field"/> + <tab class="Magento\Ui\Component\Layout\Tabs\Tab"> + <argument name="data" xsi:type="array"> + <item name="template" xsi:type="string">templates/layout/tabs/tab/default</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/components/area</item> + </item> + </argument> + </tab> + <!-- navigation --> + <nav class="Magento\Ui\Component\Layout\Tabs\Nav"> + <argument name="data" xsi:type="array"> + <item name="template" xsi:type="string">ui/tab</item> + <item name="js_config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/components/tab_group</item> + </item> + </argument> + </nav> +</components> diff --git a/app/code/Magento/Ui/view/base/ui_component/templates/form/default.xhtml b/app/code/Magento/Ui/view/base/ui_component/templates/form/default.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..a27dc54abfbf6c5e5faab7ddd31e8834e8705051 --- /dev/null +++ b/app/code/Magento/Ui/view/base/ui_component/templates/form/default.xhtml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../Ui/etc/ui_template.xsd"> + <div data-role="spinner" data-component="{{getName()}}.areas" class="admin__data-grid-loading-mask"> + <div class="grid-loader"></div> + </div> + <div data-bind="scope: '{{getName()}}.areas'" class="entry-edit form-inline"> + <!-- ko template: getTemplate() --><!-- /ko --> + </div> +</div> diff --git a/app/code/Magento/Ui/view/base/ui_component/templates/listing/default.xhtml b/app/code/Magento/Ui/view/base/ui_component/templates/listing/default.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..c56eea763192e5ce99fa92bc376ea3a33d5f7b5d --- /dev/null +++ b/app/code/Magento/Ui/view/base/ui_component/templates/listing/default.xhtml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div data-bind="scope: '{{getName()}}.{{getName()}}'" class="admin__data-grid-wrap" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../Ui/etc/ui_template.xsd"> + <div data-role="spinner" data-component="{{getName()}}.{{getName()}}.{{spinner}}" class="admin__data-grid-loading-mask"> + <div class="grid-loader"></div> + </div> + <!-- ko template: getTemplate() --><!-- /ko --> +</div> diff --git a/app/code/Magento/Ui/view/base/web/js/core/app.js b/app/code/Magento/Ui/view/base/web/js/core/app.js index 9e8f5be7e0165a310b5f7a0406d1717beb7dd5c9..5c4593bd486a312ecc1233c2a4cc2940d2025817 100644 --- a/app/code/Magento/Ui/view/base/web/js/core/app.js +++ b/app/code/Magento/Ui/view/base/web/js/core/app.js @@ -3,46 +3,13 @@ * See COPYING.txt for license details. */ define([ - 'underscore', - './renderer/renderer', - 'Magento_Ui/js/lib/registry/registry' -], function (_, Renderer, registry) { + './renderer/types', + './renderer/layout' +], function (types, layout) { 'use strict'; - function load(config, name){ - require([config.path], function(constr){ - registry.set(name, new constr(config)); - }); - } - - var global = { - init: function(data){ - this.data = {}; - - this.register() - .initRenderer(data.renderer) - .initProviders(data.providers) - .register(); - }, - - initRenderer: function(data){ - this.renderer = new Renderer(data); - - return this; - }, - - initProviders: function(providers){ - _.each(providers, load); - - return this; - }, - - register: function () { - registry.set('globalStorage', this); - - return this; - } + return function (data) { + types.set(data.types); + layout(data.components); }; - - return global.init.bind(global); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js deleted file mode 100644 index 6866bf0d0e644900b44834d5e061bd066da6bb0b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js +++ /dev/null @@ -1,241 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'jquery', - 'mage/utils', - 'Magento_Ui/js/lib/class', - 'Magento_Ui/js/lib/registry/registry' -], function(_, $, utils, Class, registry) { - 'use strict'; - - function getNodeName(parent, node, name) { - var parentName = parent && parent.name; - - if (typeof name !== 'string') { - name = node.name || name; - } - - if (parentName) { - name = parentName + '.' + name; - } - - return name; - } - - function getNodeType(parent, node){ - return node.type || (parent && parent.childType); - } - - function getDataScope(parent, node){ - var dataScope = node.dataScope, - parentScope = parent && parent.dataScope; - - return notEmpty(parentScope) ? - ( notEmpty(dataScope) ? - (parentScope + '.' + dataScope) : - parentScope ) : - (dataScope || ''); - } - - function notEmpty(value){ - return !_.isUndefined(value) && value !== ''; - } - - function mergeNode(node, config){ - return $.extend(true, {}, config, node); - } - - function additional(node){ - return _.pick(node, 'name', 'index', 'dataScope'); - } - - function loadDeps(node){ - var loaded = $.Deferred(); - - registry.get(node.deps, function(){ - loaded.resolve(node); - }); - - return loaded.promise(); - } - - function loadSource(node){ - var loaded = $.Deferred(), - source = node.component; - - require([source], function(constr){ - loaded.resolve(node, constr); - }); - - return loaded.promise(); - } - - function initComponent(node, constr){ - var component = new constr( - node.config, - additional(node) - ); - - registry.set(node.name, component); - } - - function Layout(nodes, types){ - this.types = types; - this.registry = registry.create(); - - this.run(nodes); - } - - _.extend(Layout.prototype, { - run: function(nodes, parent){ - _.each(nodes || [], this.iterator.bind(this, parent)); - - return this; - }, - - iterator: function(parent, node, name){ - var action = _.isString(node) ? - this.addChild : - this.process; - - action.apply(this, arguments); - }, - - process: function(parent, node, name) { - if(!parent && node.parent){ - return this.waitParent(node, name); - } - - if(node.template){ - return this.waitTemplate.apply(this, arguments); - } - - node = this.build.apply(this, arguments); - - if(node){ - this.addChild(parent, node.name) - .manipulate(node) - .initComponent(node) - .run(node.children, node); - } - - return this; - }, - - build: function(parent, node, name){ - var type; - - type = getNodeType.apply(null, arguments); - node = mergeNode(node, this.types.get(type)); - - node.index = node.name || name; - node.name = getNodeName(parent, node, name); - node.dataScope = getDataScope(parent, node); - - delete node.type; - - this.registry.set(node.name, node); - - return node.isTemplate ? - (node.isTemplate = false) : - node; - }, - - initComponent: function(node){ - if(!node.component){ - return this; - } - - loadDeps(node) - .then(loadSource) - .done(initComponent); - - return this; - } - }); - - _.extend(Layout.prototype, { - waitTemplate: function(parent, node, name){ - var args = _.toArray(arguments); - - this.registry.get(node.template, function(){ - this.applyTemplate.apply(this, args); - }.bind(this)); - - return this; - }, - - waitParent: function(node, name){ - var process = this.process.bind(this); - - this.registry.get(node.parent, function(parent){ - process(parent, node, name); - }); - - return this; - }, - - applyTemplate: function(parent, node, name){ - var template = this.registry.get(node.template); - - node = mergeNode(node, template); - - delete node.template; - - this.process(parent, node, name); - } - }); - - _.extend(Layout.prototype, { - manipulate: function(node) { - var name = node.name; - - if (node.appendTo) { - this.insert(name, node.appendTo, -1); - } - - if (node.prependTo) { - this.insert(name, node.prependTo, 0); - } - - if(node.insertTo){ - this.insertTo(name, node.insertTo); - } - - return this; - }, - - insert: function(item, target, position){ - registry.get(target, function(target){ - target.insert(item, position); - }); - - return this; - }, - - insertTo: function(item, targets){ - _.each(targets, function(info, target){ - this.insert(item, target, info.position); - }, this); - - return this; - }, - - addChild: function(parent, child){ - if(parent && parent.component){ - this.insert(child, parent.name); - } - - return this; - }, - - clear: function(name){ - this.registry.remove(name); - } - }); - - return Layout; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/types.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/types.js deleted file mode 100644 index 461bd8332cfd43a8ac96b4caf3c11acfcd19daf5..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/types.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'jquery', - 'mage/utils', - 'Magento_Ui/js/lib/class', - 'Magento_Ui/js/lib/registry/registry' -], function(_, $, utils, Class, registry) { - 'use strict'; - - return Class.extend({ - initialize: function(types){ - this.types = {}; - - this.set(types); - - return this; - }, - - set: function(types){ - types = types || []; - - _.each(types, function(data, type){ - this.types[type] = this.flatten(data); - }, this); - }, - - get: function(type){ - return this.types[type] || {}; - }, - - flatten: function(data){ - var extender = data.extends || [], - result = {}; - - extender = utils.stringToArray(extender); - - extender.push(data); - - extender.forEach(function(item){ - if(_.isString(item)){ - item = this.get(item); - } - - $.extend(true, result, item); - }, this); - - delete result.extends; - - return result - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/layout.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/layout.js new file mode 100644 index 0000000000000000000000000000000000000000..aac43507a35b6725c750624d7635461f88d89763 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/core/renderer/layout.js @@ -0,0 +1,230 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'jquery', + 'mageUtils', + 'uiRegistry', + './types' +], function (_, $, utils, registry, types) { + 'use strict'; + + var templates = registry.create(), + layout = {}; + + function getNodeName(parent, node, name) { + var parentName = parent && parent.name; + + if (typeof name !== 'string') { + name = node.name || name; + } + + return utils.fullPath(parentName, name); + } + + function getNodeType(parent, node) { + return node.type || parent && parent.childType; + } + + function getDataScope(parent, node) { + var dataScope = node.dataScope, + parentScope = parent && parent.dataScope; + + return !utils.isEmpty(parentScope) ? + !utils.isEmpty(dataScope) ? + parentScope + '.' + dataScope : + parentScope : + dataScope || ''; + } + + function loadDeps(node) { + var loaded = $.Deferred(); + + registry.get(node.deps, function () { + loaded.resolve(node); + }); + + return loaded.promise(); + } + + function loadSource(node) { + var loaded = $.Deferred(), + source = node.component; + + require([source], function (constr) { + loaded.resolve(node, constr); + }); + + return loaded.promise(); + } + + function initComponent(node, Constr) { + var component = new Constr(_.omit(node, 'children')); + + registry.set(node.name, component); + } + + function run(nodes, parent) { + _.each(nodes || [], layout.iterator.bind(layout, parent)); + } + + _.extend(layout, { + iterator: function (parent, node) { + var action = _.isString(node) ? + this.addChild : + this.process; + + action.apply(this, arguments); + }, + + process: function (parent, node, name) { + if (!parent && node.parent) { + return this.waitParent(node, name); + } + + if (node.template) { + return this.waitTemplate.apply(this, arguments); + } + + node = this.build.apply(this, arguments); + + if (node) { + this.addChild(parent, node) + .manipulate(node) + .initComponent(node); + + run(node.children, node); + } + + return this; + }, + + build: function (parent, node, name) { + var defaults = parent && parent.childDefaults || {}, + children = node.children, + type = getNodeType(parent, node); + + node.children = false; + + node = utils.extend({ + }, types.get(type), defaults, node); + + _.extend(node, node.config || {}, { + index: node.name || name, + name: getNodeName(parent, node, name), + dataScope: getDataScope(parent, node) + }); + + node.children = children; + + delete node.type; + delete node.config; + + if (node.isTemplate) { + node.isTemplate = false; + + templates.set(node.name, node); + + return false; + } + + return node; + }, + + initComponent: function (node) { + if (!node.component) { + return this; + } + + loadDeps(node) + .then(loadSource) + .done(initComponent); + + return this; + } + }); + + _.extend(layout, { + waitTemplate: function (parent, node) { + var args = _.toArray(arguments); + + templates.get(node.template, function () { + this.applyTemplate.apply(this, args); + }.bind(this)); + + return this; + }, + + waitParent: function (node, name) { + var process = this.process.bind(this); + + registry.get(node.parent, function (parent) { + process(parent, node, name); + }); + + return this; + }, + + applyTemplate: function (parent, node, name) { + var template = templates.get(node.template); + + node = utils.extend({}, template, node); + + delete node.template; + + this.process(parent, node, name); + } + }); + + _.extend(layout, { + manipulate: function (node) { + var name = node.name; + + if (node.appendTo) { + this.insert(name, node.appendTo, -1); + } + + if (node.prependTo) { + this.insert(name, node.prependTo, 0); + } + + if (node.insertTo) { + this.insertTo(name, node.insertTo); + } + + return this; + }, + + insert: function (item, target, position) { + registry.get(target, function (container) { + container.insert(item, position); + }); + + return this; + }, + + insertTo: function (item, targets) { + _.each(targets, function (info, target) { + this.insert(item, target, info.position); + }, this); + + return this; + }, + + addChild: function (parent, child) { + var name; + + if (parent && parent.component) { + name = child.name || child; + + this.insert(name, parent.name, child.sortOrder); + } + + return this; + } + }); + + return run; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/renderer.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/renderer.js deleted file mode 100644 index 5b7de47144ebb0ca7da594aa157c507540f2c0c9..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/core/renderer/renderer.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - './components/types', - './components/layout', - 'Magento_Ui/js/lib/class' -], function(Types, Layout, Class){ - 'use strict'; - - return Class.extend({ - initialize: function(data){ - this.types = new Types(data.types); - this.layout = new Layout(data.layout, this.types); - - return this; - }, - - render: function(data){ - this.layout.run(data.layout); - this.types.set(data.types); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/types.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/types.js new file mode 100644 index 0000000000000000000000000000000000000000..2975abbcdbe3bc86b3edcd1938735fd9b20cc0d3 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/core/renderer/types.js @@ -0,0 +1,49 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'mageUtils' +], function (_, utils) { + 'use strict'; + + var store = {}; + + function flatten(data) { + var extender = data.extends || [], + result = {}; + + extender = utils.stringToArray(extender); + + extender.push(data); + + extender.forEach(function (item) { + if (_.isString(item)) { + item = store[item] || {}; + } + + utils.extend(result, item); + }); + + delete result.extends; + + return result; + } + + return { + set: function (types) { + types = types || {}; + + utils.extend(store, types); + + _.each(types, function (data, type) { + store[type] = flatten(data); + }); + }, + + get: function (type) { + return store[type] || {}; + } + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form.js b/app/code/Magento/Ui/view/base/web/js/form.js deleted file mode 100644 index ef54b43da90399b6894c697e2f49cb46795af55a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/form.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'jquery', - 'underscore', - 'Magento_Ui/js/form/component', - 'Magento_Ui/js/lib/spinner', - './form/adapter' -], function ($, _, Component, loader, adapter) { - 'use strict'; - - function collectData(selector) { - var data = $(selector).serializeArray(), - result = {}; - - data.forEach(function (item) { - result[item.name] = item.value; - }); - - return result; - } - - return Component.extend({ - - initialize: function(){ - this._super() - .initAdapter() - .initSelector() - .hideLoader(); - - return this; - }, - - initAdapter: function(){ - adapter.on({ - 'reset': this.reset.bind(this), - 'save': this.save.bind(this, true), - 'saveAndContinue': this.save.bind(this, false) - }); - - return this; - }, - - initSelector: function(){ - this.selector = '[data-form-part='+ this.namespace +']'; - - return this; - }, - - hideLoader: function () { - loader.get(this.name).hide(); - - return this; - }, - - save: function(redirect){ - var params = this.provider.params; - - this.validate(); - - if (!params.get('invalid')) { - this.submit(redirect); - } - }, - - /** - * Submits form - */ - submit: function (redirect) { - var additional = collectData(this.selector), - provider = this.provider; - - _.each(additional, function(value, name){ - provider.data.set(name, value); - }); - - provider.save({ - redirect: redirect - }); - }, - - /** - * Validates each element and returns true, if all elements are valid. - */ - validate: function () { - var provider = this.provider; - - provider.params.set('invalid', false); - provider.data.trigger('validate'); - }, - - reset: function(){ - var data = this.provider.data; - - data.trigger('reset'); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/form/client.js b/app/code/Magento/Ui/view/base/web/js/form/client.js index 4526c775a39f69a51f1b93ac16d92153aff0182c..c8750c3129530719b24d7d8f3d8b4c4fc11b705e 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/client.js +++ b/app/code/Magento/Ui/view/base/web/js/form/client.js @@ -5,21 +5,19 @@ define([ 'jquery', 'underscore', - 'mage/utils', + 'mageUtils', 'Magento_Ui/js/lib/class' -], function($, _, utils, Class){ +], function ($, _, utils, Class) { 'use strict'; - - var defaults = {}; - function beforeSave(data, url){ + function beforeSave(data, url) { var save = $.Deferred(); - + data = utils.serialize(data); data.form_key = FORM_KEY; - - if(!url){ + + if (!url) { save.resolve(); } @@ -28,12 +26,12 @@ define([ $.ajax({ url: url, data: data, - success: function(resp){ - if(!resp.error){ + success: function (resp) { + if (!resp.error) { save.resolve(); } }, - complete: function(){ + complete: function () { $('body').trigger('processStop'); } }); @@ -46,8 +44,8 @@ define([ * Initializes DataProvider instance. * @param {Object} settings - Settings to initialize object with. */ - initialize: function(config) { - _.extend(this, defaults, config); + initialize: function (config) { + _.extend(this, config); return this; }, @@ -55,32 +53,32 @@ define([ /** * Assembles data and submits it using 'utils.submit' method */ - save: function(data, options){ - var url = this.urls.beforeSave, - save = this._save.bind(this, data, options); + save: function (data, options) { + var url = this.urls.beforeSave, + save = this._save.bind(this, data, options); beforeSave(data, url).then(save); return this; }, - _save: function(data, options){ + _save: function (data, options) { var url = this.urls.save; options = options || {}; data.form_key = FORM_KEY; - if(!options.redirect){ + if (!options.redirect) { url += 'back/edit'; } utils.submit({ - url: url, - data: data + url: url, + data: data }); return this; } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/component.js b/app/code/Magento/Ui/view/base/web/js/form/component.js deleted file mode 100644 index 5b207bfc22205f174d739688231dd187caa24fcd..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/form/component.js +++ /dev/null @@ -1,473 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'mage/utils', - 'Magento_Ui/js/lib/ko/scope', - 'Magento_Ui/js/lib/events', - 'Magento_Ui/js/lib/registry/registry' -], function(_, utils, Scope, EventsBus, registry) { - 'use strict'; - - function getOffsetFor(elems, offset){ - if(typeof offset === 'undefined'){ - offset = -1; - } - - if(offset < 0){ - offset += elems.length + 1; - } - - return offset; - } - - function getProxy(callback, data){ - if(_.isArray(data)){ - data = { - additional: data - } - } - - _.defaults(data, { - conditions: '*', - additional: [], - callback: callback - }); - - return proxy.bind(null, data); - } - - function proxy(data, value){ - var conditions = data.conditions, - args; - - if(conditions === value || conditions === '*'){ - args = data.additional.slice(); - - args.push(value); - - data.callback.apply(null, args); - } - } - - function parseSource(source, storages, data){ - var storage; - - source = utils.template(source, data); - source = source.split(':'); - - storage = source.shift(); - - return { - source: source[0], - storage: storages[storage] - } - } - - var Component = Scope.extend({ - initialize: function(config, additional){ - _.extend(this, config, additional); - - _.bindAll(this, '_insert'); - - this.initProperties() - .initObservable() - .initListeners() - .initUnique(); - - return this; - }, - - /** - * Defines various properties. - * - * @returns {Component} Chainable. - */ - initProperties: function () { - _.extend(this,{ - 'parentName': this.getPart(this.name, -2), - 'parentScope': this.getPart(this.dataScope, -2), - 'provider': registry.get(this.provider), - 'renderer': registry.get('globalStorage').renderer, - 'containers': [], - 'regions': [], - '_elems': [] - }); - - return this; - }, - - /** - * Initializes observable properties. - * - * @returns {Component} Chainable. - */ - initObservable: function(){ - this.observe({ - 'elems': [] - }); - - this.regions.forEach(function(region){ - this.observe(region, []); - }, this); - - return this; - }, - - /** - * Initializes storages listeners. - * - * @returns {Component} Chainable. - */ - initListeners: function(){ - var listeners = this.listeners || {}, - params, - iterator; - - _.each(listeners, function(handlers, source){ - params = parseSource(source, this.provider, this); - iterator = this.initListener.bind(this, params); - - _.each(handlers, iterator); - }, this); - - return this; - }, - - /** - * Initializes listeners of the unique property. - * - * @returns {Component} Chainable. - */ - initUnique: function(){ - var update = this.onUniqueUpdate.bind(this), - params = this.provider.params, - uniqueNs = this.uniqueNs; - - this.hasUnique = this.uniqueProp && uniqueNs; - - if(this.hasUnique){ - params.on('update:' + uniqueNs, update, this.name); - } - - return this; - }, - - /** - * Used as iterator for the listeners object. - * Creates callbacks and assigns it to the specified storage. - * - * @param {Object} data - - Data object that contains storage object and - it's property name that should be listened. - * @param {Object} params - Parameters of the callback. - * @param {String} callback - Callback's name. - */ - initListener: function(data, params, callback){ - var storage = data.storage, - source = data.source; - - callback = this[callback].bind(this); - callback = getProxy(callback, params); - - callback(storage.get(source)); - - storage.on('update:' + source, callback, this.name); - }, - - /** - * Called when current element was injected to another component. - * - * @param {Object} parent - Instance of a 'parent' component. - * @returns {Component} Chainable. - */ - initContainer: function(parent){ - this.containers.push(parent); - - return this; - }, - - /** - * Called when another element was added to current component. - * - * @param {Object} elem - Instance of an element that was added. - * @returns {Component} Chainable. - */ - initElement: function(elem){ - elem.initContainer(this); - - return this; - }, - - /** - * Splits incoming string and returns its' part specified by offset. - * - * @param {String} parts - * @param {Number} [offset] - * @param {String} [delimiter=.] - * @returns {String} - */ - getPart: function(parts, offset, delimiter){ - delimiter = delimiter || '.'; - parts = parts.split(delimiter); - offset = getOffsetFor(parts, offset); - - parts.splice(offset, 1); - - return parts.join(delimiter) || ''; - }, - - /** - * Returns path to components' template. - * @returns {String} - */ - getTemplate: function(){ - return this.template || 'ui/collection'; - }, - - /** - * Updates property specified in uniqueNs - * if components' unique property is set to 'true'. - * - * @returns {Component} Chainable. - */ - setUnique: function () { - var params = this.provider.params, - property = this.uniqueProp; - - if (this[property]()) { - params.set(this.uniqueNs, this.name); - } - - return this; - }, - - /** - * Callback which fires when property under uniqueNs has changed. - */ - onUniqueUpdate: function(name){ - var active = name === this.name, - property = this.uniqueProp; - - this[property](active); - } - }, EventsBus); - - - /** - * Elements manipulation methods. - */ - _.extend(Component.prototype, { - /** - * Requests specified components to insert - * them into 'elems' array starting from provided position. - * - * @param {String} elem - Name of the component to insert. - * @param {Number} [offset=-1] - Position at which to insert elements. - * @returns {Component} Chainable. - */ - insert: function(elem, offset){ - var _elems = this._elems, - insert = this._insert; - - offset = getOffsetFor(_elems, offset); - - _elems.splice(offset, 0, false); - - registry.get(elem, function(elem){ - insert(elem, offset); - }); - - return this; - }, - - /** - * Removes specified element from the 'elems' array. - * - * @param {Object} elem - Element to be removed. - * @returns {Component} Chainable. - */ - remove: function(elem) { - utils.remove(this._elems, elem); - this._update(); - - return this; - }, - - /** - * Destroys current instance along with all of its' children. - */ - destroy: function(){ - this._dropHandlers() - ._clearData() - ._clearRefs(); - }, - - /** - * Removes events listeners. - * @private - * - * @returns {Component} Chainable. - */ - _dropHandlers: function(){ - var provider = this.provider; - - this.off(); - - provider.data.off(this.name); - provider.params.off(this.name); - - return this; - }, - - /** - * Clears all data associated with component. - * @private - * - * @returns {Component} Chainable. - */ - _clearData: function(){ - var provider = this.provider, - layout = this.renderer.layout; - - provider.data.remove(this.dataScope); - provider.params.remove(this.name); - - layout.clear(this.name); - - return this; - }, - - /** - * Removes all references to current instance and - * calls 'destroy' method on all of its' children. - * @private - * - * @returns {Component} Chainable. - */ - _clearRefs: function(){ - registry.remove(this.name); - - this.containers.forEach(function(parent){ - parent.remove(this); - }, this); - - this.elems().forEach(function(child){ - child.destroy(); - }); - - return this; - }, - - /** - * Inserts provided component into 'elems' array at a specified position. - * @private - * - * @param {Object} elem - Element to insert. - * @param {Number} index - Position of the element. - */ - _insert: function(elem, index){ - this._elems[index] = elem; - - this._update() - .initElement(elem); - }, - - /** - * Synchronizes multiple elements arrays with a core '_elems' container. - * Performs elemets grouping by theirs 'displayArea' property. - * @private - * - * @returns {Component} Chainable. - */ - _update: function(){ - var _elems = _.compact(this._elems), - grouped = _.groupBy(_elems, 'displayArea'), - group; - - this.regions.forEach(function(region) { - if ((group = grouped[region])) { - this[region](group); - } - }, this); - - this.elems(_elems); - - return this; - }, - }); - - - /** - * Elements traversing methods. - */ - _.extend(Component.prototype, { - /** - * Tries to call specified method of a current component, - * otherwise delegates attempt to its' children. - * - * @param {String} target - Name of the method. - * @param [...] Arguments that will be passed to method. - * @returns {*} Result of the method calls. - */ - delegate: function(target){ - var args = _.toArray(arguments); - - target = this[target]; - - if(_.isFunction(target)){ - return target.apply(this, args.slice(1)); - } - - return this._delegate(args); - }, - - /** - * Calls 'delegate' method of all of it's children components. - * @private - * - * @param {Array} args - An array of arguments to pass to the next delegation call. - * @returns {Array} An array of delegation resutls. - */ - _delegate: function(args){ - var result; - - result = this.elems.map(function(elem){ - return elem.delegate.apply(elem, args); - }); - - return _.flatten(result); - }, - - /** - * Overrides 'EventsBus.trigger' method to implement events bubbling. - * - * @param {String} name - Name of the event. - * @param [...] Any number of arguments that should be to the events' handler. - * @returns {Boolean} False if event bubbling was canceled. - */ - trigger: function(){ - var args = _.toArray(arguments), - bubble = EventsBus.trigger.apply(this, args), - result; - - if(!bubble){ - return false; - } - - this.containers.forEach(function(parent) { - result = parent.trigger.apply(parent, args); - - if (result === false) { - bubble = false; - } - }); - - return !!bubble; - } - }); - - return Component; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/area.js b/app/code/Magento/Ui/view/base/web/js/form/components/area.js index 387260f10e1b0bca802a1965641edb123e77c1b4..b9d2884597e2c30884226894c3d44e4f194c6918 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/area.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/area.js @@ -5,12 +5,12 @@ define([ 'underscore', './tab' -], function(_, Tab) { +], function (_, Tab) { 'use strict'; return Tab.extend({ defaults: { - uniqueNs: 'activeArea', + uniqueNs: 'params.activeArea', template: 'ui/area', changed: false, loading: false @@ -20,7 +20,7 @@ define([ * Extends instance with defaults. Invokes parent initialize method. * Calls initListeners and pushParams methods. */ - initialize: function() { + initialize: function () { _.bindAll(this, 'onChildrenUpdate', 'onContentLoading', 'onContentLoaded'); return this._super(); @@ -31,7 +31,7 @@ define([ * Defines observable properties of instance. * @return {Object} - reference to instance */ - initObservable: function() { + initObservable: function () { this._super() .observe('changed loading'); @@ -44,7 +44,7 @@ define([ * @param {Object} elem * @return {Object} - reference to instance */ - initElement: function(elem){ + initElement: function (elem) { this._super(); elem.on({ @@ -61,11 +61,11 @@ define([ * Sets changed property to one incoming. * Invokes setActive method if settings * contain makeVisible property set to true. - * - * @param {Boolean} changed + * + * @param {Boolean} hasChanged */ - onChildrenUpdate: function(hasChanged){ - if(!hasChanged){ + onChildrenUpdate: function (hasChanged) { + if (!hasChanged) { hasChanged = _.some(this.delegate('hasChanged')); } @@ -75,15 +75,15 @@ define([ /** * Callback that sets loading property to true. */ - onContentLoading: function(){ + onContentLoading: function () { this.loading(true); }, /** * Callback that sets loading property to true. */ - onContentLoaded: function(){ + onContentLoaded: function () { this.loading(false); } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/collection.js b/app/code/Magento/Ui/view/base/web/js/form/components/collection.js index 0dd910f3e3ca37a6ab59212125cf0b3dfa16c7f4..5835bb0b486a089e6b1e56ba27597ce6c20c9680 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/collection.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/collection.js @@ -4,17 +4,18 @@ */ define([ 'underscore', - 'mage/utils', - 'Magento_Ui/js/lib/registry/registry', - 'Magento_Ui/js/form/component', -], function (_, utils, registry, Component) { + 'mageUtils', + 'uiRegistry', + 'uiComponent', + 'Magento_Ui/js/core/renderer/layout' +], function (_, utils, registry, Component, layout) { 'use strict'; var childTemplate = { - template: "{name}.{itemTemplate}", - parent: "{name}", - name: "{childIndex}", - dataScope: "{childIndex}" + template: '<%= $data.name %>.<%= $data.itemTemplate %>', + parent: '<%= $data.name %>', + name: '<%= $data.childIndex %>', + dataScope: '<%= name %>' }; return Component.extend({ @@ -39,7 +40,7 @@ define([ * * @param {Object} elem - Incoming child. */ - initElement: function(elem) { + initElement: function (elem) { this._super(); elem.activate(); @@ -55,12 +56,11 @@ define([ * * @returns {Collection} Chainable. */ - initChildren: function() { - var data = this.provider.data, - children = data.get(this.dataScope), - initial = this.initialItems = []; + initChildren: function () { + var children = this.source.get(this.dataScope), + initial = this.initialItems = []; - _.each(children, function(item, index) { + _.each(children, function (item, index) { initial.push(index); this.addChild(index); }, this); @@ -74,16 +74,12 @@ define([ * @param {String|Object} [index] - Index of a child. * @returns {Collection} Chainable. */ - addChild: function(index) { + addChild: function (index) { this.childIndex = !_.isString(index) ? - ('new_' + this.lastIndex++) : + 'new_' + this.lastIndex++ : index; - this.renderer.render({ - layout: [ - utils.template(childTemplate, this) - ] - }); + layout([utils.template(childTemplate, this)]); return this; }, @@ -94,12 +90,12 @@ define([ * * @returns {Boolean} */ - hasChanged: function(){ + hasChanged: function () { var initial = this.initialItems, current = this.elems.pluck('index'), changed = !utils.identical(initial, current); - return changed || this.elems.some(function(elem){ + return changed || this.elems.some(function (elem) { return _.some(elem.delegate('hasChanged')); }); }, @@ -109,12 +105,12 @@ define([ * * @returns {Array} An array of validation results. */ - validate: function(){ + validate: function () { var elems; this.allValid = true; - elems = this.elems.sortBy(function(elem){ + elems = this.elems.sortBy(function (elem) { return !elem.active(); }); @@ -130,23 +126,23 @@ define([ * @param {Object} elem - Element to run validation on. * @returns {Array} An array of validation results. */ - _validate: function(elem){ + _validate: function (elem) { var result = elem.delegate('validate'), invalid; - invalid = _.some(result, function(item){ + invalid = _.some(result, function (item) { return !item.valid; }); - if(this.allValid && invalid){ + if (this.allValid && invalid) { this.allValid = false; elem.activate(); } - return result; + return result; }, - + /** * Creates function that removes element * from collection using '_removeChild' method. @@ -155,15 +151,12 @@ define([ * Since this method is used by 'click' binding, * it requires function to invoke. */ - removeChild: function(elem) { - return function() { - var confirmed = confirm(this.removeMessage); - - if (confirmed) { - this._removeChild(elem); - } + removeChild: function (elem) { + var confirmed = confirm(this.removeMessage); - }.bind(this); + if (confirmed) { + this._removeChild(elem); + } }, /** @@ -173,7 +166,7 @@ define([ * * @param {Object} elem - Element to remove. */ - _removeChild: function(elem) { + _removeChild: function (elem) { var isActive = elem.active(), first; @@ -189,4 +182,3 @@ define([ } }); }); - diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js b/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js index 44413dd4555972fc7b8f86323921d10d04584640..d8b4bf4cc4192fe038f7d1c74c00af1f23f4daa6 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils', + 'mageUtils', '../tab' ], function (_, utils, Tab) { 'use strict'; @@ -16,12 +16,12 @@ define([ /** * Parses incoming data and returnes result merged with default preview config - * + * * @param {Object|String} data * @return {Object} */ - function parsePreview(data){ - if (typeof data === 'string') { + function parsePreview(data) { + if (typeof data == 'string') { data = { items: data }; @@ -34,10 +34,9 @@ define([ return Tab.extend({ defaults: { - template: 'ui/form/components/collection/item', - label: '', - uniqueNs: 'activeCollectionItem', - previewTpl: 'ui/form/components/collection/preview' + label: '', + uniqueNs: 'activeCollectionItem', + previewTpl: 'ui/form/components/collection/preview' }, /** @@ -50,25 +49,23 @@ define([ }, /** - * Calls initProperties of parent class, initializes properties - * of instance - * + * Calls initProperties of parent class, initializes properties + * of instance. + * * @return {Object} - reference to instance */ initProperties: function () { this._super(); this.displayed = []; - - utils.add(this.regions, 'body', 'head'); return this; }, /** * Calls initObservable of parent class, initializes observable - * properties of instance - * + * properties of instance. + * * @return {Object} - reference to instance */ initObservable: function () { @@ -76,7 +73,7 @@ define([ this.observe({ 'noPreview': true, - 'indexed': {} + 'indexed': {} }); return this; @@ -98,73 +95,76 @@ define([ /** * Adds element to observable indexed object of instance - * + * * @param {Object} elem * @return {Object} - reference to instance */ insertToIndexed: function (elem) { var indexed = this.indexed(); - + indexed[elem.index] = elem; this.indexed(indexed); - + return this; }, /** - * Formats incoming previews array via parsePreview function - * + * Formats incoming previews array via parsePreview function. + * * @param {Array} previews * @return {Array} - formatted previews */ - formatPreviews: function(previews){ + formatPreviews: function (previews) { return previews.map(parsePreview); }, /** * Creates string view of previews - * + * * @param {Object} data * @return {Strict} - formatted preview string */ - buildPreview: function(data){ + buildPreview: function (data) { var preview = this.getPreview(data.items), - prefix = data.prefix; + prefix = data.prefix; return prefix + preview.join(data.separator); }, /** * Defines if instance has preview for incoming data - * + * * @param {Object} data * @return {Boolean} */ - hasPreview: function(data){ + hasPreview: function (data) { return !!this.getPreview(data.items).length; }, /** * Creates an array of previews for elements specified in incoming * items array, calls updatePreview afterwards. - * + * * @param {Array} items - An array of element's indexes. * @returns {Array} An array of previews. */ - getPreview: function(items){ - var elems = this.indexed(), - displayed = this.displayed, + getPreview: function (items) { + var elems = this.indexed(), + displayed = this.displayed, preview; - items = items.map(function(index){ + items = items.map(function (index) { var elem = elems[index]; - preview = elem ? elem.delegate('getPreview') : []; - preview = _.compact(preview).join(', '); + preview = elem ? elem.delegate('getPreview') : ''; + + preview = Array.isArray(preview) ? + _.compact(preview).join(', ') : + preview; utils.toggle(displayed, index, !!preview); - + return preview; }); @@ -173,4 +173,4 @@ define([ return _.compact(items); } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js b/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js index 752a678fc72fe58805fe89e38696d144fa1881aa..2369c3740f4688f8116628a1cb561170342c544b 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js @@ -3,13 +3,15 @@ * See COPYING.txt for license details. */ define([ - './collapsible' -], function(Collapsible) { + 'Magento_Ui/js/lib/collapsible' +], function (Collapsible) { 'use strict'; return Collapsible.extend({ defaults: { - template: 'ui/fieldset/fieldset' + template: 'ui/form/fieldset', + collapsible: false, + opened: true } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/group.js b/app/code/Magento/Ui/view/base/web/js/form/components/group.js index 2a23cb48a54da5f3e6d2764a39554a4558691928..325e4e0f4295e06d3326d94d75ab08573db58d99 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/group.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/group.js @@ -4,45 +4,25 @@ */ define([ 'underscore', - '../component', - 'mage/utils' -], function(_, Component, utils) { + 'uiComponent' +], function (_, Component) { 'use strict'; - - function extractData(container, field){ - var data, - value; - - container.some(function(item){ - value = item[field]; - - if(_.isFunction(value)){ - value = value(); - } - - return !item.hidden() && (data = value); - }); - - return data || ''; - } return Component.extend({ defaults: { - hidden: false, - label: '', - required: false, - template: 'ui/group/group', - fieldTemplate: 'ui/group/field', - breakLine: true + hidden: false, + label: '', + required: false, + template: 'ui/group/group', + fieldTemplate: 'ui/form/field', + breakLine: true }, /** * Extends this with defaults and config. * Then calls initObservable, iniListenes and extractData methods. - * - * @param {Object} config */ - initialize: function() { + initialize: function () { _.bindAll(this, 'toggle'); return this._super(); @@ -51,12 +31,12 @@ define([ /** * Calls initObservable of parent class. * Defines observable properties of instance. - * + * * @return {Object} - reference to instance */ - initObservable: function(){ + initObservable: function () { this._super() - .observe('hidden label required'); + .observe('hidden required'); return this; }, @@ -64,41 +44,25 @@ define([ /** * Assignes onUpdate callback to update event of incoming element. * Calls extractData method. - * @param {Object} element + * @param {Object} elem * @return {Object} - reference to instance */ - initElement: function(elem){ + initElement: function (elem) { this._super(); elem.on({ 'toggle': this.toggle }); - this.extractData(); - - return this; - }, - - /** - * Extracts label and required properties from child elements - * - * @return {Object} - reference to instance - */ - extractData: function(){ - var elems = this.elems(); - - this.label(extractData(elems, 'label')); - this.required(extractData(elems, 'required')); - return this; }, /** * Sets incoming value to hidden observable, calls extractData method - * + * * @param {Boolean} value */ - toggle: function(value){ + toggle: function (value) { this.extractData() .hidden(value); }, @@ -119,4 +83,4 @@ define([ return this.elems.getLength() > 1; } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/html.js b/app/code/Magento/Ui/view/base/web/js/form/components/html.js index d9dd813981d5f03ea6abbaca1deef638664b6bed..e8cf03cc4e1bc266f16987cf65a653842f8b432b 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/html.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/html.js @@ -5,8 +5,8 @@ define([ 'jquery', 'underscore', - '../component' -], function($, _, Component) { + 'uiComponent' +], function ($, _, Component) { 'use strict'; return Component.extend({ @@ -14,14 +14,17 @@ define([ content: '', showSpinner: false, loading: false, - template: 'ui/content/content' + template: 'ui/content/content', + listens: { + loading: 'toggleLoadState' + } }, /** * Extends instance with default config, calls 'initialize' method of * parent, calls 'initAjaxConfig' */ - initialize: function() { + initialize: function () { _.bindAll(this, 'onContainerToggle', 'onDataLoaded'); this._super() @@ -32,33 +35,18 @@ define([ /** * Calls 'initObservable' method of parent, initializes observable - * properties of instance - * + * properties of instance + * * @return {Object} - reference to instance */ - initObservable: function() { + initObservable: function () { this._super() .observe('content loading'); return this; }, - /** - * Calls 'initListeners' method of parent, defines instance's subscriptions - * - * @return {Object} - reference to instance - */ - initListeners: function() { - this._super(); - - this.loading.subscribe(function(value) { - this.trigger(value ? 'loading' : 'loaded'); - }, this); - - return this; - }, - - initContainer: function(parent) { + initContainer: function (parent) { this._super(); parent.on('active', this.onContainerToggle); @@ -68,13 +56,15 @@ define([ /** * Initializes default ajax config on instance - * + * * @return {Object} - reference to instance */ - initAjaxConfig: function(){ + initAjaxConfig: function () { this.ajaxConfig = { - url: this.source, - data: { FORM_KEY: FORM_KEY }, + url: this.url, + data: { + FORM_KEY: FORM_KEY + }, success: this.onDataLoaded }; @@ -83,40 +73,44 @@ define([ /** * Calls 'loadData' if both 'active' variable and 'shouldLoad' - * property are truthy - * + * property are truthy + * * @param {Boolean} active */ - onContainerToggle: function(active) { + onContainerToggle: function (active) { if (active && this.shouldLoad()) { this.loadData(); } }, + toggleLoadState: function (value) { + this.trigger(value ? 'loading' : 'loaded'); + }, + /** - * Defines if instance has 'content' property defined - * + * Defines if instance has 'content' property defined. + * * @return {Boolean} [description] */ - hasData: function() { + hasData: function () { return !!this.content(); }, /** * Defines if instance should load external data - * + * * @return {Boolean} */ - shouldLoad: function() { - return this.source && !this.hasData() && !this.loading(); + shouldLoad: function () { + return this.url && !this.hasData() && !this.loading(); }, /** * Sets loading property to true, makes ajax call - * + * * @return {Object} - reference to instance */ - loadData: function() { + loadData: function () { this.loading(true); $.ajax(this.ajaxConfig); @@ -126,25 +120,25 @@ define([ /** * Ajax's request success handler. Calls 'updateContent' passing 'data' - * to it, then sets 'loading' property to false - * + * to it, then sets 'loading' property to false. + * * @param {String} data */ - onDataLoaded: function(data) { + onDataLoaded: function (data) { this.updateContent(data) .loading(false); }, /** * Sets incoming data 'content' property's value - * + * * @param {String} content * @return {Object} - reference to instance */ - updateContent: function(content) { + updateContent: function (content) { this.content(content); return this; } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/tab.js b/app/code/Magento/Ui/view/base/web/js/form/components/tab.js index c15e513883219106dfc7639dcf7b6ef6fc41a38e..61560892e3e9ddd8dc3885644eb3d874a50ea9fb 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/tab.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/tab.js @@ -3,8 +3,8 @@ * See COPYING.txt for license details. */ define([ - '../component' -], function(Component) { + 'uiComponent' +], function (Component) { 'use strict'; return Component.extend({ @@ -18,7 +18,7 @@ define([ * Extends instance with defaults. Invokes parent initialize method. * Calls initListeners and pushParams methods. */ - initialize: function() { + initialize: function () { this._super() .setUnique(); }, @@ -28,29 +28,29 @@ define([ * Defines observable properties of instance. * @return {Object} - reference to instance */ - initObservable: function() { + initObservable: function () { this._super() .observe('active wasActivated'); return this; }, - - onUniqueUpdate: function(name){ + + onUniqueUpdate: function (name) { var active = name === this.name; this._super(); this.trigger('active', active); }, - + /** * Sets active property to true, then invokes pushParams method. */ - activate: function(){ + activate: function () { this.active(true); this.wasActivated(true); this.setUnique(); } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/tab_group.js b/app/code/Magento/Ui/view/base/web/js/form/components/tab_group.js index 625d2ba848c6bfd0c60d6453e3835fb072dd0748..474814559d3cae9f0f364bdf593332ecb12654bb 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/tab_group.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/tab_group.js @@ -4,12 +4,18 @@ */ define([ 'underscore', - './collapsible', - 'Magento_Ui/js/lib/spinner' -], function(_, Collapsible, loader) { + 'Magento_Ui/js/lib/collapsible' +], function (_, Collapsible) { 'use strict'; - + return Collapsible.extend({ + defaults: { + listens: { + '<%= provider %>:data.validate': 'onValidate' + }, + collapsible: false, + opened: true + }, /** * Invokes initElement method of parent class, calls 'initActivation' method @@ -17,27 +23,10 @@ define([ * @param {Object} elem * @returns {Object} - reference to instance */ - initElement: function(elem){ + initElement: function (elem) { this._super() - .initActivation(elem) - .hideLoader(); - - return this; - }, - - /** - * Binds 'onValidate' method as handler for data storage's 'validate' event - * - * @return {Object} - reference to instance - */ - initListeners: function(){ - var data = this.provider.data, - handler = this.onValidate.bind(this); - - this._super(); + .initActivation(elem); - data.on('validate', handler, this.name); - return this; }, @@ -48,40 +37,36 @@ define([ * @param {Object} elem * @returns {Object} - reference to instance */ - initActivation: function(elem){ + initActivation: function (elem) { var elems = this.elems(), isFirst = !elems.indexOf(elem); - if(isFirst || elem.active()){ + if (isFirst || elem.active()) { elem.activate(); } return this; }, - hideLoader: function () { - loader.get(this.name).hide(); - }, - /** * Delegates 'validate' method on element, then reads 'invalid' property - * of params storage, and if defined, activates element, sets + * of params storage, and if defined, activates element, sets * 'allValid' property of instance to false and sets invalid's * 'focused' property to true. * * @param {Object} elem */ - validate: function(elem){ - var params = this.provider.params, + validate: function (elem) { + var source = this.source, result = elem.delegate('validate'), invalid = false; - _.some(result, function(item){ + _.some(result, function (item) { return !item.valid && (invalid = item.target); }); - if (invalid && !params.get('invalid')) { - params.set('invalid', invalid); + if (invalid && !source.get('params.invalid')) { + source.set('params.invalid', true); elem.activate(); invalid.focused(true); @@ -90,16 +75,16 @@ define([ /** * Sets 'allValid' property of instance to true, then calls 'validate' method - * of instance for each element + * of instance for each element. */ - onValidate: function(){ + onValidate: function () { var elems; - elems = this.elems.sortBy(function(elem){ + elems = this.elems.sortBy(function (elem) { return !elem.active(); - }); + }); - elems.each(this.validate, this); + elems.forEach(this.validate, this); } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js index e1d66754af6285e4a6938ca4f878a3a2b7fdca3d..1e5f1168ffbe0fd7c4ba037f65fe91f53f35bee8 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js @@ -4,59 +4,69 @@ */ define([ 'underscore', - 'mage/utils', - 'Magento_Ui/js/form/component', + 'mageUtils', + 'uiComponent', 'Magento_Ui/js/lib/validation/validator' ], function (_, utils, Component, validator) { 'use strict'; - - /** - * Checks wether the incoming value is not empty, - * e.g. not 'null' or 'undefined' - * - * @param {*} value - Value to check. - * @returns {Boolean} - */ - function isEmpty(value){ - return _.isUndefined(value) || _.isNull(value); - } return Component.extend({ defaults: { - hidden: false, - preview: '', - focused: false, - required: false, - disabled: false, - tmpPath: 'ui/form/element/', - tooltipTpl: 'ui/form/element/helper/tooltip', - input_type: 'input', - placeholder: '', - description: '', - label: '', - error: '', - notice: '' + visible: true, + preview: '', + focused: false, + required: false, + disabled: false, + tmpPath: 'ui/form/element/', + tooltipTpl: 'ui/form/element/helper/tooltip', + input_type: 'input', + placeholder: '', + description: '', + label: '', + error: '', + notice: '', + + listens: { + value: 'onUpdate', + visible: 'setPreview', + '<%= provider %>:data.reset': 'reset', + '<%= provider %>:data.validate': 'validate' + }, + + links: { + value: '<%= provider %>:<%= dataScope %>' + }, + + exports: { + visible: '<%= provider %>:config.<%= name %>.visible' + }, + + imports: { + setPreview: '<%= name %>:value' + } }, /** * Invokes initialize method of parent class, contains initialization * logic - * + * * @param {Object} config - form element configuration */ initialize: function () { - _.bindAll(this, 'onUpdate', 'reset'); + _.bindAll(this, 'reset'); + + this._super(); + + this.initialValue = this.getInititalValue(); - this._super() - .setHidden(this.hidden()) - .store(this.value()); + this.value(this.initialValue); return this; }, /** * Initializes observable properties of instance - * + * * @returns {Abstract} Chainable. */ initObservable: function () { @@ -64,11 +74,8 @@ define([ this._super(); - this.initialValue = this.getInititalValue(); - - this.observe('error disabled focused preview hidden') + this.observe('error disabled focused preview visible') .observe({ - 'value': this.initialValue, 'required': !!rules['required-entry'] }); @@ -77,7 +84,7 @@ define([ /** * Initializes regular properties of instance. - * + * * @returns {Abstract} Chainable. */ initProperties: function () { @@ -86,87 +93,37 @@ define([ this._super(); _.extend(this, { - 'uid': uid, - 'noticeId': 'notice-' + this.uid, - 'inputName': utils.serializeName(this.dataScope) - }); - - _.defaults(this, { - 'template': this.tmpPath + this.input_type + 'uid': uid, + 'noticeId': 'notice-' + uid, + 'inputName': utils.serializeName(this.dataScope) }); return this; }, - /** - * Initializes instance's listeners. - * - * @returns {Abstract} Chainable. - */ - initListeners: function(){ - var provider = this.provider, - data = provider.data; - - this._super(); - - data.on('reset', this.reset, this.name); - - this.value.subscribe(this.onUpdate); - - return this; - }, - /** * Gets initial value of element - * + * * @returns {*} Elements' value. */ - getInititalValue: function(){ - var data = this.provider.data, - values = [data.get(this.dataScope), this.default], + getInititalValue: function () { + var values = [this.value(), this.default], value; - values.some(function(v){ - return !isEmpty(value = v); + values.some(function (v) { + return !utils.isEmpty(value = v); }); - return isEmpty(value) ? '': value; + return utils.isEmpty(value) ? '' : value; }, /** * Sets value to preview observable - * + * * @returns {Abstract} Chainable. */ - setPreview: function(value){ - this.preview(this.hidden() ? '' : value); - - return this; - }, - - /** - * Returnes unwrapped preview observable. - * - * @returns {String} Value of the preview observable. - */ - getPreview: function(){ - return this.preview(); - }, - - /** - * Calls 'setHidden' passing true to it. - */ - hide: function(){ - this.setHidden(true); - - return this; - }, - - /** - * Calls 'setHidden' passing false to it. - */ - show: function(){ - this.setHidden(false); + setPreview: function (value) { + this.preview(!this.visible() ? '' : value); return this; }, @@ -175,25 +132,29 @@ define([ * Sets 'value' as 'hidden' propertie's value, triggers 'toggle' event, * sets instance's hidden identifier in params storage based on * 'value'. - * + * * @returns {Abstract} Chainable. */ - setHidden: function(isHidden){ - var params = this.provider.params; - - this.hidden(isHidden); - - this.setPreview(this.value()) - .trigger('toggle', isHidden); + setVisible: function (isVisible) { + this.visible(isVisible); - params.set(this.name + '.hidden', isHidden); + this.trigger('toggle', isVisible); return this; }, + /** + * Returnes unwrapped preview observable. + * + * @returns {String} Value of the preview observable. + */ + getPreview: function () { + return this.preview(); + }, + /** * Checkes if element has addons - * + * * @returns {Boolean} */ hasAddons: function () { @@ -205,29 +166,20 @@ define([ * * @returns {Boolean} */ - hasChanged: function(){ + hasChanged: function () { var notEqual = this.value() != this.initialValue; - return this.hidden() ? false : notEqual; + return !this.visible() ? false : notEqual; }, - /** - * Stores element's value to registry by element's path value - * @param {*} value - current value of form element - * @returns {Abstract} Chainable. - */ - store: function (value) { - var data = this.provider.data; - - data.set(this.dataScope, value); - - return this; + hasData: function () { + return !utils.isEmpty(this.value()); }, /** * Sets value observable to initialValue property. */ - reset: function(){ + reset: function () { this.value(this.initialValue); }, @@ -235,18 +187,18 @@ define([ * Validates itself by it's validation rules using validator object. * If validation of a rule did not pass, writes it's message to * 'error' observable property. - * + * * @returns {Boolean} True, if element is invalid. */ validate: function () { - var value = this.value(), - msg = validator(this.validation, value), - isValid = this.hidden() || !msg; + var value = this.value(), + msg = validator(this.validation, value), + isValid = !this.visible() || !msg; this.error(msg); return { - valid: isValid, + valid: isValid, target: this }; }, @@ -254,12 +206,10 @@ define([ /** * Callback that fires when 'value' property is updated. */ - onUpdate: function (value) { - this.store(value) - .setPreview(value) - .trigger('update', this.hasChanged()); + onUpdate: function () { + this.trigger('update', this.hasChanged()); this.validate(); } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js b/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js index 8b13f063ce2052649d4c0ce6c335e1d43b6c5063..4782c853d210b11696c71f31d8d855a8e64eb4b0 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js @@ -10,28 +10,26 @@ define([ return Abstract.extend({ /** * Converts the result of parent 'getInitialValue' call to boolean - * + * * @return {Boolean} */ - getInititalValue: function(){ + getInititalValue: function () { return !!+this._super(); }, /** * Calls 'store' method of parent, if value is defined and instance's * 'unique' property set to true, calls 'setUnique' method - * + * * @param {*} value * @return {Object} - reference to instance */ - store: function() { - this._super(); - + onUpdate: function () { if (this.hasUnique) { this.setUnique(); } - return this; + return this._super(); } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/date.js b/app/code/Magento/Ui/view/base/web/js/form/element/date.js index 6e53005137b69fac101db602d58b930d24c24473..4943d845c0504730963115b9bee9e6187e4f72e4 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/date.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/date.js @@ -4,13 +4,21 @@ */ define([ 'moment', + 'mageUtils', './abstract' -], function (moment, Abstract) { +], function (moment, utils, Abstract) { 'use strict'; return Abstract.extend({ defaults: { - dateFormat: 'MM/DD/YYYY' + dateFormat: 'MM/DD/YYYY', + options: {} + }, + + initProperties: function () { + this.dateFormat = utils.normalizeDate(this.dateFormat); + + return this._super(); }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js index 1afc75a8837ef240151de7f884dc8cef07ae2fdb..a6dc9e3b3afe600527a5b0fd470b05547b955789 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils', + 'mageUtils', './select' ], function (_, utils, Select) { 'use strict'; @@ -17,10 +17,10 @@ define([ /** * Calls 'getInitialValue' of parent and if the result of it is not empty * string, returs it, else returnes caption or first found option's value - * + * * @returns {Number|String} */ - getInititalValue: function(){ + getInititalValue: function () { var value = this._super(); return _.isString(value) ? value.split(',') : value; @@ -31,7 +31,7 @@ define([ * @returns {Boolean} */ hasChanged: function () { - var value = this.value(), + var value = this.value(), initial = this.initialValue; return !utils.identical(value, initial); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js b/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js index 066d99b1d21078ebe36d2bf12077a15643ce002d..97cb38dcbb07b9aa0018cb54f6535f2c6a2c8c3c 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js @@ -4,62 +4,37 @@ */ define([ 'underscore', - 'Magento_Ui/js/lib/registry/registry', + 'uiRegistry', './abstract' ], function (_, registry, Abstract) { 'use strict'; return Abstract.extend({ - /** - * Extended list of Listeners - * - * @return {this} - */ - initListeners: function () { - this._super() - .update() - .provider.data.on('update:' + this.parentScope + '.country_id', this.update.bind(this)); - - return this; + defaults: { + imports: { + update: '<%= parentName %>.country_id:value' + } }, - /** - * Fix _postcode_ depend on _country_id_ change: - * - If country in list "Zip/Postal Code is Optional countries" then - * - field "postcode" should not be required - * - * @returns {this} - */ - update: function () { - var parentScope = this.getPart(this.getPart(this.name, -2), -2), - option, - postcode = this; - - registry.get(parentScope + '.country_id.0', function (countryComponent) { - var value = countryComponent.value(); - - if (!value) { // empty value discard logic - return; - } + update: function (value) { + var country = registry.get(this.parentName + '.' + 'country_id'), + options = country.indexedOptions, + option; - countryComponent - .options() - .some(function (el) { - option = el; + if (!value) { + return; + } - return el.value === value; - }); + option = options[value]; - if (!option.is_region_required) { - postcode.error(false); - postcode.validation = _.omit(postcode.validation, 'required-entry'); - } else { - postcode.validation['required-entry'] = true; - } - postcode.required(!!option.is_region_required); - }); + if (!option.is_region_required) { + this.error(false); + this.validation = _.omit(this.validation, 'required-entry'); + } else { + this.validation['required-entry'] = true; + } - return this; + this.required(!!option.is_region_required); } }); }); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index bd2e6d6d13ca04562b5cfe2472ff119ac00c9d54..2dd476c24a50aaadee6dd7484f8d23c8f329a63f 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -4,44 +4,37 @@ */ define([ 'underscore', - 'mage/utils', - './abstract' -], function (_, utils, Abstract) { + 'mageUtils', + 'uiRegistry', + './abstract', + 'Magento_Ui/js/core/renderer/layout' +], function (_, utils, registry, Abstract, layout) { 'use strict'; var inputNode = { - name: '{index}_input', - type: 'input', - parent: '{parentName}', - dataScope: '{customEntry}', - config: { - hidden: true, - label: '{label}', - listeners: { - "params:{parentName}.{index}.hidden":{ - "hide": { - "conditions": false - }, - "show": { - "conditions": true - } - } - } - } + parent: '<%= $data.parentName %>', + type: 'form.input', + name: '<%= $data.index %>_input', + dataScope: '<%= $data.customEntry %>', + sortOrder: { + after: '<%= $data.name %>' + }, + displayArea: 'body', + label: '<%= $data.label %>' }; /** * Parses incoming options, considers options with undefined value property * as caption - * + * * @param {Array} nodes * @return {Object} */ - function parseOptions(nodes){ + function parseOptions(nodes) { var caption, value; - nodes = _.map(nodes, function(node) { + nodes = _.map(nodes, function (node) { value = node.value; if (value == null || value === '') { @@ -55,24 +48,24 @@ define([ return { options: _.compact(nodes), - caption: caption + caption: caption || false }; } /** * Recursively loops over data to find non-undefined, non-array value - * + * * @param {Array} data * @return {*} - first non-undefined value in array */ - function findFirst(data){ + function findFirst(data) { var value; - data.some(function(node){ + data.some(function (node) { value = node.value; - if(Array.isArray(value)){ - value = findFirst(value); + if (Array.isArray(value)) { + value = findFirst(value); } return !_.isUndefined(value); @@ -81,9 +74,27 @@ define([ return value; } + function indexOptions(data, result) { + var value; + + result = result || {}; + + data.forEach(function (item) { + value = item.value; + + if (Array.isArray(value)) { + indexOptions(value, result); + } else { + result[value] = item; + } + }); + + return result; + } + return Abstract.extend({ defaults: { - template: 'ui/form/element/select' + customName: '<%= parentName %>.<%= index %>_input' }, /** @@ -91,24 +102,47 @@ define([ * and options, and invokes initialize method of AbstractElement class. * If instance's 'customEntry' property is set to true, calls 'initInput' */ - initialize: function (config) { - this.initOptions(config) - ._super(); - - if(this.customEntry){ + initialize: function () { + this._super(); + + if (this.customEntry) { this.initInput(); } + if (this.filterBy) { + this.initFilter(); + } + + return this; + }, + + /** + * Parses options and merges the result with instance + * + * @param {Object} config + * @returns {Select} Chainable. + */ + initConfig: function (config) { + var result = parseOptions(config.options); + + if (config.caption) { + delete result.caption; + } + + _.extend(config, result); + + this._super(); + return this; }, /** * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions' * properties, calls 'setOptions' passing options to it - * + * * @returns {Select} Chainable. */ - initObservable: function(){ + initObservable: function () { this._super(); this.initialOptions = this.options; @@ -119,31 +153,23 @@ define([ return this; }, - /** - * Parses options and merges the result with instance - * - * @param {Object} config - * @returns {Select} Chainable. - */ - initOptions: function(config){ - var result = parseOptions(config.options); + initFilter: function () { + var filter = this.filterBy; - _.extend(config, result); + this.setLinks({ + filter: filter.target + }, 'imports'); return this; }, /** * Creates input from template, renders it via renderer. - * + * * @returns {Select} Chainable. */ - initInput: function(){ - this.renderer.render({ - layout: [ - utils.template(inputNode, this) - ] - }); + initInput: function () { + layout([utils.template(inputNode, this)]); return this; }, @@ -151,54 +177,67 @@ define([ /** * Calls 'getInitialValue' of parent and if the result of it is not empty * string, returs it, else returnes caption or first found option's value - * + * * @returns {Number|String} */ - getInititalValue: function(){ + getInititalValue: function () { var value = this._super(); - if(value !== ''){ + if (value !== '') { return value; } - - if(!this.caption){ + + if (!this.caption) { return findFirst(this.options); } }, /** * Filters 'initialOptions' property by 'field' and 'value' passed, - * calls 'setOptions' passing the result to it - * - * @param {String} field + * calls 'setOptions' passing the result to it + * * @param {*} value + * @param {String} field */ - filter: function(field, value){ + filter: function (value, field) { var source = this.initialOptions, result; - result = _.filter(source, function(item){ + field = field || this.filterBy.field; + + result = _.filter(source, function (item) { return item[field] === value; }); this.setOptions(result); }, + toggleInput: function (isVisible) { + registry.get(this.customName, function (input) { + input.setVisible(isVisible); + }); + }, + /** - * Sets 'data' to 'options' observable array, if instance has + * Sets 'data' to 'options' observable array, if instance has * 'customEntry' property set to true, calls 'setHidden' method * passing !options.length as a parameter - * + * * @param {Array} data * @returns {Select} Chainable. */ - setOptions: function(data){ - this.indexedOptions = _.indexBy(data, 'value'); + setOptions: function (data) { + var isVisible; + + this.indexedOptions = indexOptions(data); this.options(data); - - if(this.customEntry){ - this.setHidden(!data.length); + + if (this.customEntry) { + isVisible = !!data.length; + + this.setVisible(isVisible); + this.toggleInput(!isVisible); } return this; @@ -207,17 +246,17 @@ define([ /** * Processes preview for option by it's value, and sets the result * to 'preview' observable - * + * * @param {String} value * @returns {Select} Chainable. */ - setPreview: function(value){ - var option = this.indexedOptions[value], + setPreview: function (value) { + var option = this.indexedOptions[value], preview = option ? option.label : ''; - + this.preview(preview); return this; } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/textarea.js b/app/code/Magento/Ui/view/base/web/js/form/element/textarea.js index a575e352e6ffcbdce395b56b78cb722123c8f3b8..ebd8a85fac67c2c055c0c1a1ee47ebc1bfb9a93c 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/textarea.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/textarea.js @@ -14,4 +14,4 @@ define([ template: 'ui/form/element/textarea' } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/form.js b/app/code/Magento/Ui/view/base/web/js/form/form.js new file mode 100644 index 0000000000000000000000000000000000000000..2a192c20c2463e29397750f0ade0e147ac0d80bd --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/form/form.js @@ -0,0 +1,95 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'uiComponent', + 'Magento_Ui/js/lib/spinner', + './adapter' +], function (_, Component, loader, adapter) { + 'use strict'; + + function collectData(selector) { + var items = document.querySelectorAll(selector), + result = {}; + + items = Array.prototype.slice.call(items); + + items.forEach(function (item) { + result[item.name] = item.value; + }); + + return result; + } + + return Component.extend({ + initialize: function () { + this._super() + .initAdapter() + .hideLoader(); + + return this; + }, + + initAdapter: function () { + adapter.on({ + 'reset': this.reset.bind(this), + 'save': this.save.bind(this, true), + 'saveAndContinue': this.save.bind(this, false) + }); + + return this; + }, + + initProperties: function () { + this._super(); + + this.selector = '[data-form-part=' + this.namespace + ']'; + + return this; + }, + + hideLoader: function () { + loader.get(this.name).hide(); + + return this; + }, + + save: function (redirect) { + this.validate(); + + if (!this.source.get('params.invalid')) { + this.submit(redirect); + } + }, + + /** + * Submits form + */ + submit: function (redirect) { + var additional = collectData(this.selector), + source = this.source; + + _.each(additional, function (value, name) { + source.set('data.' + name, value); + }); + + source.save({ + redirect: redirect + }); + }, + + /** + * Validates each element and returns true, if all elements are valid. + */ + validate: function () { + this.source.set('params.invalid', false); + this.source.trigger('data.validate'); + }, + + reset: function () { + this.source.trigger('data.reset'); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/provider.js b/app/code/Magento/Ui/view/base/web/js/form/provider.js index ccf45e2f2f0fdb55efd2f1285b3b0081912551a0..c388763fc4ce7b25cc535cfcbdba5419ccbd0e03 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/provider.js +++ b/app/code/Magento/Ui/view/base/web/js/form/provider.js @@ -4,72 +4,36 @@ */ define([ 'underscore', - './client', - './storages', - 'Magento_Ui/js/lib/registry/registry', - 'Magento_Ui/js/lib/class', - 'Magento_Ui/js/lib/events', -], function(_, Client, storages, registry, Class, EventsBus){ + 'Magento_Ui/js/lib/provider', + './client' +], function (_, Provider, Client) { 'use strict'; - - var defaults = { - stores: ['data', 'params'] - }; - return Class.extend({ - /** - * Initializes DataProvider instance. - * @param {Object} settings - Settings to initialize object with. - */ - initialize: function(settings) { - _.extend(this, defaults, settings, settings.config || {}); - - this.initStorages() + return Provider.extend({ + initialize: function () { + this._super() .initClient(); - }, - - /** - * Creates instances of storage objects. - * @returns {DataProvider} Chainable. - */ - initStorages: function() { - var storage, - config; - - this.stores.forEach(function(store) { - storage = storages[store]; - config = this[store] || {}; - - if(Array.isArray(config)){ - config = {}; - } - - this[store] = new storage(config); - }, this); return this; }, - initClient: function(){ + initClient: function () { this.client = new Client({ urls: { - beforeSave: this.validate_url, - save: this.submit_url - } + beforeSave: this.data.validate_url, + save: this.data.submit_url + } }); return this; }, - /** - * Assembles data and submits it using 'utils.submit' method - */ - save: function(options){ - var data = this.data.get(); - + save: function (options) { + var data = this.get('data'); + this.client.save(data, options); return this; } - }, EventsBus); -}); \ No newline at end of file + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/storages.js b/app/code/Magento/Ui/view/base/web/js/form/storages.js deleted file mode 100644 index 9eba0b970be472943833cdaa2286c1ab29abbe85..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/form/storages.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/** - * Assembles storages for form provider - */ -define([ - 'Magento_Ui/js/lib/storage/storage' -], function(Storage){ - 'use strict'; - - return { - meta: Storage, - params: Storage, - data: Storage, - dump: Storage - } -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/actions.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/actions.js new file mode 100644 index 0000000000000000000000000000000000000000..33a095e64e806024affa49638b9fe8bb40566e79 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/actions.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + './column' +], function (_, Column) { + 'use strict'; + + return Column.extend({ + defaults: { + headerTmpl: 'ui/grid/columns/actions', + bodyTmpl: 'ui/grid/cells/actions' + }, + + getDisplayed: function (actions) { + actions = _.filter(actions, function (action) { + return !('hidden' in action) || !action.hidden; + }); + + this.displayed = actions; + + return actions; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/column.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/column.js new file mode 100644 index 0000000000000000000000000000000000000000..dd91490b300a037bb258775ffdd39f15f5900a52 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/column.js @@ -0,0 +1,53 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'uiComponent' +], function (Component) { + 'use strict'; + + return Component.extend({ + defaults: { + headerTmpl: 'ui/grid/columns/text', + bodyTmpl: 'ui/grid/cells/text', + sortable: false, + visible: true, + defaultVisible: '<%= visible %>', + imports: { + visible: '<%= provider %>:config.columns.<%= index %>.visible' + } + }, + + resetVisible: function () { + this.visible(this.defaultVisible); + }, + + getClickUrl: function (row) { + var field = row[this.actionField], + action = field && field[this.clickAction]; + + return action ? action.href : ''; + }, + + isClickable: function (row) { + return !!this.getClickUrl(row); + }, + + redirect: function (url) { + window.location.href = url; + }, + + getLabel: function (data) { + return data; + }, + + getHeader: function () { + return this.headerTmpl; + }, + + getBody: function () { + return this.bodyTmpl; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js new file mode 100644 index 0000000000000000000000000000000000000000..0e319022a8b040491976c758cc2476c5286af112 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'mageUtils', + 'moment', + './sortable' +], function (utils, moment, Sortable) { + 'use strict'; + + return Sortable.extend({ + defaults: { + dateFormat: 'MMM D, YYYY h:mm:ss A' + }, + + initProperties: function () { + this.dateFormat = utils.normalizeDate(this.dateFormat); + + return this._super(); + }, + + getLabel: function (data) { + return moment(data).format(this.dateFormat); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/multiselect.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/multiselect.js new file mode 100644 index 0000000000000000000000000000000000000000..a88d981dac96cee9b0538a52732252ba27fb0ac1 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/multiselect.js @@ -0,0 +1,331 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'mage/translate', + './column' +], function (_, $t, Column) { + 'use strict'; + + return Column.extend({ + defaults: { + headerTmpl: 'ui/grid/columns/multiselect', + bodyTmpl: 'ui/grid/cells/multiselect', + menuVisible: false, + excludeMode: false, + allSelected: false, + indetermine: false, + selected: [], + excluded: [], + ns: '<%= provider %>:params', + actions: [{ + value: 'selectAll', + label: $t('Select all') + }, { + value: 'deselectAll', + label: $t('Deselect all') + }, { + value: 'selectPage', + label: $t('Select all on this page') + }, { + value: 'deselectPage', + label: $t('Deselect all on this page') + }], + + imports: { + totalRecords: '<%= provider %>:data.totalRecords', + rows: '<%= provider %>:data.items' + }, + + listens: { + '<%= ns %>.applyFilters': 'deselectAll', + selected: 'onSelectedChange', + rows: 'onRowsChange' + } + }, + + /** + * Initializes observable properties. + * + * @returns {Multiselect} Chainable. + */ + initObservable: function () { + this._super() + .observe([ + 'menuVisible', + 'selected', + 'excluded', + 'excludeMode', + 'totalSelected', + 'allSelected', + 'indetermine' + ]); + + return this; + }, + + /** + * Toggles menu with a list of select actions. + */ + toggleMenu: function () { + this.menuVisible(!this.menuVisible()); + }, + + /** + * Hides menu with a list of select actions. + */ + hideMenu: function () { + this.menuVisible(false); + }, + + /** + * Selects all grid records, even those that are not visible on the page. + */ + selectAll: function () { + this.excludeMode(true); + + this.clearExcluded() + .selectPage(); + + return this; + }, + + /** + * Deselects all grid records. + */ + deselectAll: function () { + this.excludeMode(false); + + this.clearExcluded() + .deselectPage(); + this.selected.removeAll(); + + return this; + }, + + /** + * Selects or deselects all records. + */ + toggleSelectAll: function () { + return this.allSelected() ? + this.deselectAll() : + this.selectAll(); + }, + + /** + * Selects all records on the current page. + */ + selectPage: function () { + this.selected( + _.union(this.selected(), this.getIds()) + ); + + return this; + }, + + /** + * Deselects all records on the current page. + */ + deselectPage: function () { + var currentPageIds = this.getIds(); + this.selected.remove(function (value) { + return currentPageIds.indexOf(value) !== -1; + }); + + return this; + }, + + /** + * Clears the array of not selected records. + * + * @returns {Multiselect} Chainable. + */ + clearExcluded: function () { + this.excluded.removeAll(); + + return this; + }, + + /** + * Retrieve all id's from available records. + * + * @param {Boolean} [exclude] - Whether to exclude not selected ids' from result. + * @returns {Array} An array of ids'. + */ + getIds: function (exclude) { + var items = this.rows(), + ids = _.pluck(items, this.indexField); + + return exclude ? + _.difference(ids, this.excluded()) : + ids; + }, + + /** + * Recalculates list of the excluded records. + * Changes value of `excluded`. + * + * @param {Array} selected - List of the currently selected records. + * @returns {Multiselect} Chainable. + */ + updateExcluded: function (selected) { + var excluded = this.excluded(), + fromPage = _.difference(this.getIds(), selected); + + excluded = _.union(excluded, fromPage); + excluded = _.difference(excluded, selected); + + this.excluded(excluded); + + return this; + }, + + /** + * Calculates number of the selected records. + * Changes value of `totalSelected`. + * + * @returns {Multiselect} Chainable. + */ + countSelected: function () { + var total = this.totalRecords(), + excluded = this.excluded().length, + selected = this.selected().length; + + if (this.excludeMode()) { + selected = total - excluded; + } + + this.totalSelected(selected); + + return this; + }, + + /** + * Exports selections to the data provider. + */ + exportSelections: function () { + var data = {}, + type; + + type = this.excludeMode() ? 'excluded' : 'selected'; + + data[type] = this[type](); + data.total = this.totalSelected(); + + this.source.set('config.multiselect', data); + }, + + /** + * Defines if provided select/deselect action is relevant. + * + * @param {String} actionId - Id of the action to be checked. + * @returns {Boolean} + */ + isActionRelevant: function (actionId) { + var pageIds = this.getIds().length, + multiplePages = pageIds < this.totalRecords(); + + switch (actionId) { + case 'selectPage': + + return multiplePages && !this.isPageSelected(true); + + case 'deselectPage': + + return multiplePages && this.isPageSelected(); + + case 'selectAll': + + return !this.allSelected(); + + case 'deselectAll': + + return this.totalSelected() > 0; + } + + return true; + }, + + /** + * Defines if current page has selected records on it. + * + * @param {Boolean} [all=false] - If set to 'true' checks that every + * record on the page is selected. Otherwise checks that + * page has some selected records. + * @returns {Boolean} + */ + isPageSelected: function (all) { + var pageIds = this.getIds(), + selected = this.selected(), + excluded = this.excluded(), + iterator = all ? 'every' : 'some'; + + if (this.allSelected()) { + return true; + } + + if (this.excludeMode()) { + return pageIds[iterator](function (id) { + return !~excluded.indexOf(id); + }); + } + + return pageIds[iterator](function (id) { + return !!~selected.indexOf(id); + }); + }, + + /** + * Updates values of the 'allSelected' + * and 'indetermine' properties. + */ + updateState: function () { + var selected = this.selected().length, + excluded = this.excluded().length, + totalSelected = this.totalSelected(), + totalRecords = this.totalRecords(), + allSelected = totalRecords && totalSelected === totalRecords; + + if (this.excludeMode()) { + if (excluded === totalRecords) { + this.deselectAll(); + } + } else if (totalRecords && selected === totalRecords) { + this.selectAll(); + } + + this.allSelected(allSelected); + this.indetermine(totalSelected > 0 && !allSelected); + + return this; + }, + + /** + * Callback method to handle change of the selected items. + * + * @param {Array} selected - List of the currently selected items. + */ + onSelectedChange: function (selected) { + this.updateExcluded(selected) + .countSelected() + .updateState() + .exportSelections(); + }, + + /** + * Is invoked when rows has changed. Recalculates selected items + * based on "selectMode" property. + */ + onRowsChange: function () { + var newSelected; + + if (this.excludeMode()) { + newSelected = _.union(this.getIds(true), this.selected()); + + this.selected(newSelected); + } + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js new file mode 100644 index 0000000000000000000000000000000000000000..75acdbca9c150981798d0d689a75c0beae1e13d8 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js @@ -0,0 +1,24 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + './sortable' +], function (Sortable) { + 'use strict'; + + return Sortable.extend({ + getLabel: function (data) { + var options = this.options || [], + label = ''; + + options.some(function (item) { + label = item.label; + + return item.value == data; + }); + + return label; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/sortable.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/sortable.js new file mode 100644 index 0000000000000000000000000000000000000000..6e4221ae565fcb0718211fed3c81ef518cbe4dc5 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/sortable.js @@ -0,0 +1,76 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + './column' +], function (Column) { + 'use strict'; + + return Column.extend({ + defaults: { + sortable: true, + sorting: false, + classes: { + 'asc': '_ascend', + 'desc': '_descend' + }, + listens: { + '<%= provider %>:params.sorting.field': 'onSortChange', + sorting: 'setSortClass push' + } + }, + + initObservable: function () { + this._super() + .observe('sorting sortClass'); + + this.setSortClass(this.sorting()); + + return this; + }, + + sort: function (enabled) { + var direction; + + direction = enabled !== false ? + this.sorting() ? + this.toggleDirection() : + 'asc' : + false; + + this.sorting(direction); + }, + + push: function (sorting) { + if (!sorting) { + return; + } + + this.source.set('params.sorting', { + field: this.index, + direction: sorting + }); + + this.source.reload(); + }, + + toggleDirection: function () { + return this.sorting() === 'asc' ? + 'desc' : + 'asc'; + }, + + setSortClass: function (sorting) { + var sortClass = this.classes[sorting] || ''; + + this.sortClass(sortClass); + }, + + onSortChange: function (field) { + if (field !== this.index) { + this.sort(false); + } + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/controls/columns.js b/app/code/Magento/Ui/view/base/web/js/grid/controls/columns.js new file mode 100644 index 0000000000000000000000000000000000000000..c46a1b81cf6e3bac1c6da0a38f749baefd1d74f0 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/controls/columns.js @@ -0,0 +1,115 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'mageUtils', + 'mage/translate', + 'underscore', + 'Magento_Ui/js/lib/collapsible' +], function (utils, $t, _, Collapsible) { + 'use strict'; + + return Collapsible.extend({ + defaults: { + template: 'ui/grid/controls/columns', + viewportSize: 18, + viewportMaxSize: 30 + }, + + /** + * Action Reset + */ + reset: function () { + this.delegate('resetVisible'); + }, + + /** + * Action Apply + */ + apply: function () { + var data = {}, + current; + + this.close(); + + current = this.source.get('config.columns') || {}; + + this.elems().forEach(function (elem) { + data[elem.index] = { + visible: elem.visible() + }; + }); + + utils.extend(current, data); + + this.source.store('config.columns', current); + }, + + /** + * Action Cancel + */ + cancel: function () { + var previous = this.source.get('config.columns'), + config; + + this.close(); + + if (!previous) { + return; + } + + this.elems().forEach(function (elem) { + config = previous[elem.index] || {}; + + elem.visible(config.visible); + }); + }, + + /** + * Helper, wich helps to stop resizing and + * @returns {Boolean} + */ + hasOverflow: function () { + return this.elems().length > this.viewportSize; + }, + + /** + * Helper, checks + * - if less than one item choosen + * - if more then viewportMaxSize choosen + * @param {Object} elem + * @returns {Boolean} + */ + isDisabled: function (elem) { + var count = this.countVisible(), + isLast = elem.visible() && count === 1, + isTooMuch = count > this.viewportMaxSize; + + return isLast || isTooMuch; + }, + + /** + * Helper, returns number of visible checkboxes + * @returns {Number} + */ + countVisible: function () { + return this.elems().filter(function (elem) { + return elem.visible(); + }).length; + }, + + /** + * Compile header message from headerMessage setting. + * Expects Underscore template format + * @param {String} text - underscore-format template + * @returns {String} + */ + getHeaderMessage: function (text) { + return _.template(text)({ + visible: this.countVisible(), + total: this.elems().length + }); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/controls/view.js b/app/code/Magento/Ui/view/base/web/js/grid/controls/view.js new file mode 100644 index 0000000000000000000000000000000000000000..4ad292e5801d2c2b96ec491265d8bc68013a297d --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/controls/view.js @@ -0,0 +1,24 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'Magento_Ui/js/lib/collapsible' +], function (Collapsible) { + 'use strict'; + + return Collapsible.extend({ + defaults: { + template: 'ui/grid/controls/view', + sampleData: [{ + label: 'Cameras' + }, { + label: 'Products by weight' + }, { + label: 'Greg\'s view' + }, { + label: 'Default View' + }] + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js new file mode 100644 index 0000000000000000000000000000000000000000..e196cfad0db8d89c98de0e003961d90b7a28d8ab --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js @@ -0,0 +1,76 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'Magento_Ui/js/lib/collapsible' +], function (_, Collapsible) { + 'use strict'; + + function extractPreview(elem) { + return { + label: elem.label, + preview: elem.delegate('getPreview'), + elem: elem + }; + } + + function hasData(elem) { + return elem.delegate('hasData'); + } + + function resetValue(elem) { + return elem.delegate('reset'); + } + + return Collapsible.extend({ + defaults: { + template: 'ui/grid/filters/filters', + listens: { + active: 'extractPreviews' + } + }, + + initObservable: function () { + this._super() + .observe({ + active: [], + previews: [] + }); + + return this; + }, + + apply: function () { + this.extractActive(); + + this.source.trigger('params.applyFilters'); + this.source.reload(); + }, + + reset: function (filter) { + filter ? + resetValue(filter) : + this.active.each(resetValue); + + this.apply(); + }, + + extractActive: function () { + var active = this.elems.filter(hasData); + + this.active(active); + + return this; + }, + + extractPreviews: function (elems) { + var previews = elems.map(extractPreview); + + this.previews(_.compact(previews)); + + return this; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/group.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/group.js new file mode 100644 index 0000000000000000000000000000000000000000..d59ba8fd942d41f53607587eecc69ecd8d5bd090 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/group.js @@ -0,0 +1,32 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'Magento_Ui/js/form/components/group' +], function (_, Group) { + 'use strict'; + + return Group.extend({ + defaults: { + template: 'ui/grid/filters/elements/group' + }, + + hasData: function () { + return this.elems.some(function (elem) { + return elem.delegate('hasData'); + }); + }, + + getPreview: function () { + var previews = this.elems.map(function (elem) { + if (elem.hasData()) { + return elem.label + ': ' + elem.getPreview(); + } + }); + + return _.compact(previews).join(' '); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/listing.js b/app/code/Magento/Ui/view/base/web/js/grid/listing.js new file mode 100644 index 0000000000000000000000000000000000000000..3885e4f3a34d28f34ae5bc4d7be6e5731106afbd --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/listing.js @@ -0,0 +1,46 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'uiComponent', + 'Magento_Ui/js/lib/spinner' +], function (Component, loader) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'ui/grid/listing', + imports: { + rows: '<%= provider %>:data.items' + }, + listens: { + '<%= provider %>:reload': 'showLoader', + '<%= provider %>:reloaded': 'hideLoader' + } + }, + + initialize: function () { + this._super() + .hideLoader(); + + return this; + }, + + hideLoader: function () { + loader.get(this.name).hide(); + }, + + showLoader: function () { + loader.get(this.name).show(); + }, + + getColspan: function () { + return this.elems().length; + }, + + hasData: function () { + return !!this.rows().length; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js new file mode 100644 index 0000000000000000000000000000000000000000..35c792feaba23e40c19c68f2609171c798983297 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -0,0 +1,40 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'mageUtils', + 'Magento_Ui/js/lib/collapsible' +], function (_, utils, Collapsible) { + 'use strict'; + + return Collapsible.extend({ + defaults: { + template: 'ui/grid/actions', + noItems: 'You haven\'t selected any items!' + }, + + applyAction: function (action) { + var proceed = true, + selections = this.source.get('config.multiselect'); + + if (!selections || !selections.total) { + proceed = false; + + alert(this.noItems); + } + + if (proceed && action.confirm) { + proceed = window.confirm(action.confirm); + } + + if (proceed) { + utils.submit({ + url: action.url, + data: selections + }); + } + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/paging.js b/app/code/Magento/Ui/view/base/web/js/grid/paging.js new file mode 100644 index 0000000000000000000000000000000000000000..cb6e5367cab328e9aa411d4023b9a6daa205b387 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/paging.js @@ -0,0 +1,148 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'uiComponent' +], function (ko, Component) { + 'use strict'; + + /** + * Returns closest existing page number to page argument + * @param {Number} value + * @param {Number} max + * @returns {Number} closest existing page number + */ + function getInRange(value, max) { + return Math.min(Math.max(1, value), max); + } + + return Component.extend({ + defaults: { + template: 'ui/grid/paging', + pageSize: 20, + current: 1, + + imports: { + totalSelected: '<%= provider %>:config.multiselect.total', + totalRecords: '<%= provider %>:data.totalRecords' + }, + + exports: { + pageSize: '<%= provider %>:params.paging.pageSize', + current: '<%= provider %>:params.paging.current', + pages: '<%= provider %>:data.pages' + }, + + listens: { + 'pageSize': 'onSizeChange', + 'pageSize current': 'reload', + 'pageSize totalRecords': 'countPages' + } + }, + + initialize: function () { + this._super() + .countPages(); + + return this; + }, + + initObservable: function () { + this._super(); + + this._current = ko.pureComputed({ + read: function () { + return +this.current(); + }, + + /** + * Validates page change according to user's input. + * Sets current observable to result of validation. + * Calls reload method then. + */ + write: function (value) { + var valid; + + value = +value; + valid = !isNaN(value) ? getInRange(value, this.pages()) : 1; + + this.current(valid); + this._current.notifySubscribers(value); + }, + + owner: this + }); + + return this; + }, + + /** + * Increments current observable prop by val and call reload method + * @param {String} val + */ + go: function (val) { + var current = this.current; + + current(current() + val); + }, + + /** + * Calls go method with 1 as agrument + */ + next: function () { + this.go(1); + }, + + /** + * Calls go method with -1 as agrument + */ + prev: function () { + this.go(-1); + }, + + /** + * Compares current and pages observables and returns boolean result + * + * @returns {Boolean} is current equal to pages property + */ + isLast: function () { + return this.current() === this.pages(); + }, + + /** + * Compares current observable to 1. + * + * @returns {Boolean} is current page first + */ + isFirst: function () { + return this.current() === 1; + }, + + reload: function () { + this.source.reload(); + }, + + /** + * Calculates number of pages. + */ + countPages: function () { + var pages = Math.ceil(this.totalRecords() / this.pageSize()); + + this.pages(pages || 1); + }, + + /** + * Is being triggered on user interaction with page size select. + * Resets current page to first if needed. + */ + onSizeChange: function () { + var size = this.pageSize(); + + if (size * this.current() > this.totalRecords()) { + this.current(1); + } + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/provider.js b/app/code/Magento/Ui/view/base/web/js/grid/provider.js new file mode 100644 index 0000000000000000000000000000000000000000..52868c288ca8391c4851e0f7ab9cdf62a268ef69 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/provider.js @@ -0,0 +1,37 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'underscore', + 'mageUtils', + 'Magento_Ui/js/lib/provider' +], function ($, _, utils, Provider) { + 'use strict'; + + return Provider.extend({ + initialize: function () { + utils.limit(this, 'reload', 50); + _.bindAll(this, 'onReload'); + + return this._super(); + }, + + reload: function () { + this.trigger('reload'); + + $.ajax({ + url: this.data.update_url, + method: 'GET', + data: this.get('params'), + dataType: 'json' + }).done(this.onReload); + }, + + onReload: function (data) { + this.set('data', data); + this.trigger('reloaded'); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/class.js b/app/code/Magento/Ui/view/base/web/js/lib/class.js index 1cc6e8955cf81820349c0d61c8ada238ee11c5a5..be53c19ea135fb9566ecbfaece5ce7128e77afe3 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/class.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/class.js @@ -3,8 +3,9 @@ * See COPYING.txt for license details. */ define([ - 'underscore' -], function(_) { + 'underscore', + 'mageUtils' +], function (_, utils) { 'use strict'; var superReg = /\b_super\b/; @@ -15,7 +16,7 @@ define([ * @param {Function} method - Method to be checked. * @returns {Boolean} */ - function hasSuper(method){ + function hasSuper(method) { return _.isFunction(method) && superReg.test(method); } @@ -27,13 +28,13 @@ define([ * @param {Function} method - Method to be wrapped. * @returns {Function} Wrapped method. */ - function superWrapper(parent, name, method){ - return function(){ - var superTmp = this._super, - args = arguments, + function superWrapper(parent, name, method) { + return function () { + var superTmp = this._super, + args = arguments, result; - this._super = function(){ + this._super = function () { var superArgs = arguments.length ? arguments : args; return parent[name].apply(this, superArgs); @@ -44,52 +45,49 @@ define([ this._super = superTmp; return result; - } + }; } /** * Analogue of Backbone.extend function. * - * @param {Object} extender - - * Object, that describes the prototype of + * @param {Object} extender - Object, that describes the prototype of * created constructor. - * @param {...Object} Multiple amount of mixins. * @returns {Function} New constructor. */ - function extend(extender){ - var parent = this, + function extend(extender) { + var parent = this, + defaults = extender.defaults || {}, parentProto = parent.prototype, - defaults = extender.defaults || {}, - child, - childProto, - mixins; + child; - child = function(){ - _.defaults(this, defaults); - - parent.apply(this, arguments); - }; + defaults = defaults || {}; + extender = extender || {}; delete extender.defaults; - childProto = child.prototype = Object.create(parentProto); + if (extender.hasOwnProperty('constructor')) { + child = extender.constructor; + } else { + child = function () { + parent.apply(this, arguments); + }; + } + + defaults = utils.extend({}, parent.defaults, defaults); - childProto.constructor = child; + child.prototype = Object.create(parentProto); + child.prototype.constructor = child; - _.each(extender, function(method, name){ - childProto[name] = hasSuper(method) ? + _.each(extender, function (method, name) { + child.prototype[name] = hasSuper(method) ? superWrapper(parentProto, name, method) : method; }); - mixins = _.toArray(arguments).slice(1); - - mixins.forEach(function(mixin){ - _.extend(childProto, mixin); - }); - child.__super__ = parentProto; - child.extend = extend; + child.extend = extend; + child.defaults = defaults; return child; } @@ -101,9 +99,10 @@ define([ this.initialize.apply(this, arguments); } - Class.prototype.initialize = function(){}; + Class.prototype.initialize = function () {}; Class.extend = extend; + Class.defaults = {}; return Class; }); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/collapsible.js b/app/code/Magento/Ui/view/base/web/js/lib/collapsible.js similarity index 54% rename from app/code/Magento/Ui/view/base/web/js/form/components/collapsible.js rename to app/code/Magento/Ui/view/base/web/js/lib/collapsible.js index 00b4768b37127a684fb8e9eea00274d9c0b4fe67..5b831ae4460aa4d82483a2d3ee02ae7adc320fb5 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/collapsible.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/collapsible.js @@ -3,22 +3,22 @@ * See COPYING.txt for license details. */ define([ - 'Magento_Ui/js/form/component' -], function(Component) { + 'uiComponent' +], function (Component) { 'use strict'; return Component.extend({ defaults: { - collapsible: false, - opened: true + opened: false, + collapsible: true }, /** * Initializes 'opened' observable, calls 'initObservable' of parent - * + * * @return {Object} - reference to instance */ - initObservable: function(){ + initObservable: function () { this._super() .observe('opened'); @@ -27,25 +27,21 @@ define([ /** * Toggles 'active' observable, triggers 'active' event - * + * * @return {Object} - reference to instance */ - toggle: function() { - var opened = this.opened, - active = opened(!opened()); - - this.trigger('active', active); + toggleOpened: function () { + if (this.collapsible) { + this.opened(!this.opened()); + } return this; }, - /** - * Invokes 'toggle' method if instance has 'collapsible' property set to true - */ - onClick: function(){ - if(this.collapsible){ - this.toggle(); + close: function () { + if (this.collapsible) { + this.opened(false); } } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component.js b/app/code/Magento/Ui/view/base/web/js/lib/component.js deleted file mode 100644 index 7d179bcf36633a131021962d53eb57a06cc3964d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/component.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'Magento_Ui/js/lib/registry/registry' -], function(registry) { - 'use strict'; - - /** - * Extends configuration that will be retrieved from the data provider - * with configuration that is stored in a 'baseConfig' object. - * @param {Object} provider - DataProvider instance. - * @param {Object} baseConfig - Basic configuration. - * @returns {Object} Resulting configurational object. - */ - function getConfig(provider, baseConfig) { - var configs = provider.config.get('components'), - storeConfig = configs[baseConfig.name] || {}; - - return _.extend({ - provider: provider - }, storeConfig, baseConfig); - } - - /** - * Creates new instance of a grids' component. - * @param {Object} data - - Data object that was passed while creating component initializer. - * @param {Object} base - - Basic configuration. - */ - function init(data, base) { - var providerName = base.parent_name, - component = providerName + ':' + base.name; - - if (registry.has(component)) { - return; - } - - registry.get(providerName, function(provider) { - var config = getConfig(provider, base); - - registry.set(component, new data.constr(config)); - }); - } - - return function(data) { - return init.bind(this, data); - }; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/core.js b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js new file mode 100644 index 0000000000000000000000000000000000000000..f5944f007f83e4bb005c576f0c005fb8c1b7faf3 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js @@ -0,0 +1,222 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'mageUtils', + 'underscore', + 'uiRegistry' +], function (ko, utils, _, registry) { + 'use strict'; + + /** + * Wrapper for ko.observable and ko.observableArray. + * Assignes one or another ko property to obj[key] + * @param {Object} obj - object to store property to + * @param {String} key - key + * @param {*} value - initial value of observable + */ + function observe(obj, key, value) { + var method = Array.isArray(value) ? 'observableArray' : 'observable'; + + if (!ko.isObservable(obj[key])) { + obj[key] = ko[method](value); + } else { + obj[key](value); + } + } + + return { + defaults: { + parentName: '<%= $data.getPart(name, -2) %>', + parentScope: '<%= $data.getPart(dataScope, -2) %>', + template: 'ui/collection', + containers: [], + _elems: [] + }, + + initialize: function (options) { + _.bindAll(this, '_insert'); + + this.initConfig(options) + .initProperties() + .initObservable() + .initUnique() + .initLinks() + .setListners(this.listens); + + return this; + }, + + initConfig: function (options) { + var defaults = this.constructor.defaults, + config = utils.extend({}, defaults, options); + + config = utils.template(config, this); + + _.extend(this, config); + + return this; + }, + + /** + * Defines various properties. + * + * @returns {Component} Chainable. + */ + initProperties: function () { + this.regions = []; + this.source = registry.get(this.provider); + + return this; + }, + + /** + * Initializes observable properties. + * + * @returns {Component} Chainable. + */ + initObservable: function () { + this.observe({ + 'elems': [] + }); + + this.regions.forEach(function (region) { + this.observe(region, []); + }, this); + + return this; + }, + + initLinks: function () { + _.each({ + both: this.links, + exports: this.exports, + imports: this.imports + }, this.setLinks, this); + + return this; + }, + + /** + * Initializes listeners of the unique property. + * + * @returns {Component} Chainable. + */ + initUnique: function () { + var update = this.onUniqueUpdate.bind(this), + uniqueNs = this.uniqueNs; + + this.hasUnique = this.uniqueProp && uniqueNs; + + if (this.hasUnique) { + this.source.on(uniqueNs, update, this.name); + } + + return this; + }, + + /** + * Called when current element was injected to another component. + * + * @param {Object} parent - Instance of a 'parent' component. + * @returns {Component} Chainable. + */ + initContainer: function (parent) { + this.containers.push(parent); + + return this; + }, + + /** + * Called when another element was added to current component. + * + * @param {Object} elem - Instance of an element that was added. + * @returns {Component} Chainable. + */ + initElement: function (elem) { + elem.initContainer(this); + + return this; + }, + + /** + * Splits incoming string and returns its' part specified by offset. + * + * @param {String} parts + * @param {Number} [offset] + * @param {String} [delimiter=.] + * @returns {String} + */ + getPart: function (parts, offset, delimiter) { + delimiter = delimiter || '.'; + parts = parts.split(delimiter); + offset = utils.formatOffset(parts, offset); + + parts.splice(offset, 1); + + return parts.join(delimiter) || ''; + }, + + /** + * Returns path to components' template. + * @returns {String} + */ + getTemplate: function () { + return this.template; + }, + + /** + * Updates property specified in uniqueNs + * if components' unique property is set to 'true'. + * + * @returns {Component} Chainable. + */ + setUnique: function () { + var property = this.uniqueProp; + + if (this[property]()) { + this.source.set(this.uniqueNs, this.name); + } + + return this; + }, + + /** + * If 2 params passed, path is considered as key. + * Else, path is considered as object. + * Assignes props to this based on incoming params + * @param {Object|String} path + */ + observe: function (path) { + var type = typeof path; + + if (type === 'string') { + path = path.split(' '); + } + + if (Array.isArray(path)) { + path.forEach(function (key) { + observe(this, key, this[key]); + }, this); + } else if (type === 'object') { + _.each(path, function (value, key) { + observe(this, key, value); + }, this); + } + + return this; + }, + + /** + * Callback which fires when property under uniqueNs has changed. + */ + onUniqueUpdate: function (name) { + var active = name === this.name, + property = this.uniqueProp; + + this[property](active); + } + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/links.js b/app/code/Magento/Ui/view/base/web/js/lib/component/links.js new file mode 100644 index 0000000000000000000000000000000000000000..4434ca6896eeb5150ad679b8f7be9b8e5d724889 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/links.js @@ -0,0 +1,128 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'underscore', + 'mageUtils', + 'Magento_Ui/js/lib/registry/registry' +], function (ko, _, utils, registry) { + 'use strict'; + + function extractData(str) { + var data = str.split(':'); + + return { + component: data[0], + prop: data[1] + }; + } + + function update(target, prop, value) { + if (_.isFunction(target[prop])) { + target[prop](value); + } else if (target.set) { + target.set(prop, value); + } else { + target[prop] = value; + } + } + + function imports(owner, target, ownerProp, targetProp, auto) { + var callback = update.bind(null, owner, ownerProp), + value; + + value = target.get ? + target.get(targetProp) : + utils.nested(target, targetProp); + + if (ko.isObservable(value)) { + value.subscribe(callback); + value = value(); + } else if (target.on) { + target.on(targetProp, callback); + } + + if (auto && typeof value !== 'undefined') { + callback(value); + } + } + + function exports(owner, target, ownerProp, targetProp, auto) { + var to = update.bind(null, target, targetProp); + + ownerProp = owner[ownerProp]; + + ownerProp.subscribe(to); + + if (auto) { + to(ownerProp()); + } + } + + function links(owner, target, ownerProp, direction) { + if (!ko.isObservable(owner[ownerProp]) && !_.isFunction(owner[ownerProp])) { + owner.observe(ownerProp); + } + + target = extractData(target); + + registry.get(target.component, function (component) { + var args = [owner, component, ownerProp, target.prop, true]; + + switch (direction) { + case 'imports': + imports.apply(null, args); + break; + + case 'exports': + exports.apply(null, args); + break; + + case 'both': + imports.apply(null, args); + exports.apply(null, args); + break; + } + }); + } + + function listen(owner, target, callback) { + target = extractData(target); + + if (!target.prop) { + target.prop = target.component; + target.component = owner.name; + } + + registry.get(target.component, function (component) { + imports(owner, component, callback, target.prop); + }); + } + + return { + setLinks: function (data, direction) { + var owner = this; + + _.each(data, function (target, prop) { + links(owner, target, prop, direction); + }); + }, + + setListners: function (listeners) { + var owner = this; + + _.each(listeners, function (callbacks, sources) { + sources = sources.split(' '); + callbacks = callbacks.split(' '); + + sources.forEach(function (target) { + callbacks.forEach(function (callback) { + listen(owner, target, callback); + }); + }); + }); + } + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/main.js b/app/code/Magento/Ui/view/base/web/js/lib/component/main.js new file mode 100644 index 0000000000000000000000000000000000000000..9b5f99cf7cb895c378c072e26103c579fd219df0 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/main.js @@ -0,0 +1,21 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + './core', + './links', + './manip', + './traversal', + 'Magento_Ui/js/lib/class', + 'Magento_Ui/js/lib/ko/initialize' +], function (_, core, links, manip, traversal, Class) { + 'use strict'; + + var extenders; + + extenders = _.extend({}, core, links, manip, traversal); + + return Class.extend(extenders); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js b/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js new file mode 100644 index 0000000000000000000000000000000000000000..301beed7381d053c19f734a094d00db2aada6205 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js @@ -0,0 +1,190 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'underscore', + 'mageUtils', + 'uiRegistry' +], function (ko, _, utils, registry) { + 'use strict'; + + function getIndex(container, target) { + var result; + + container.some(function (item, index) { + result = index; + + return item && (item.name === target || item === target); + }); + + return result; + } + + function compact(container) { + return container.filter(utils.isObject); + } + + function reserve(container, elem, position) { + var offset = position, + target; + + if (_.isObject(position)) { + target = position.after || position.before; + offset = getIndex(container, target); + + if (position.after) { + ++offset; + } + } + + offset = utils.formatOffset(container, offset); + + container[offset] ? + container.splice(offset, 0, elem) : + container[offset] = elem; + + return offset; + } + + return { + getRegion: function (name) { + var regions = this.regions; + + if (!regions[name]) { + regions[name] = ko.observable([]); + } + + return regions[name]; + }, + + updateRegion: function (items, name) { + var region = this.getRegion(name); + + region(items); + }, + + /** + * Requests specified components to insert + * them into 'elems' array starting from provided position. + * + * @param {String} elem - Name of the component to insert. + * @param {Number} [position=-1] - Position at which to insert elements. + * @returns {Component} Chainable. + */ + insert: function (elem, position) { + reserve(this._elems, elem, position); + registry.get(elem, this._insert); + + return this; + }, + + /** + * Removes specified element from the 'elems' array. + * + * @param {Object} elem - Element to be removed. + * @returns {Component} Chainable. + */ + remove: function (elem) { + utils.remove(this._elems, elem); + this._update(); + + return this; + }, + + /** + * Destroys current instance along with all of its' children. + */ + destroy: function () { + this._dropHandlers() + ._clearData() + ._clearRefs(); + }, + + /** + * Removes events listeners. + * @private + * + * @returns {Component} Chainable. + */ + _dropHandlers: function () { + this.off(); + + this.source.off(this.name); + + return this; + }, + + /** + * Clears all data associated with component. + * @private + * + * @returns {Component} Chainable. + */ + _clearData: function () { + this.source.remove(this.dataScope); + this.source.remove('params.' + this.name); + + return this; + }, + + /** + * Removes all references to current instance and + * calls 'destroy' method on all of its' children. + * @private + * + * @returns {Component} Chainable. + */ + _clearRefs: function () { + registry.remove(this.name); + + this.containers.forEach(function (parent) { + parent.remove(this); + }, this); + + this.elems().forEach(function (child) { + child.destroy(); + }); + + return this; + }, + + /** + * Inserts provided component into 'elems' array at a specified position. + * @private + * + * @param {Object} elem - Element to insert. + */ + _insert: function (elem) { + var index = this._elems.indexOf(elem.name); + + if (!~index) { + return; + } + + this._elems[index] = elem; + + this._update() + .initElement(elem); + }, + + /** + * Synchronizes multiple elements arrays with a core '_elems' container. + * Performs elemets grouping by theirs 'displayArea' property. + * @private + * + * @returns {Component} Chainable. + */ + _update: function () { + var _elems = compact(this._elems), + grouped = _.groupBy(_elems, 'displayArea'); + + _.each(grouped, this.updateRegion, this); + + this.elems(_elems); + + return this; + } + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/traversal.js b/app/code/Magento/Ui/view/base/web/js/lib/component/traversal.js new file mode 100644 index 0000000000000000000000000000000000000000..d94770d90f9e888b0ff08869c268663064e0c9d1 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/traversal.js @@ -0,0 +1,76 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'Magento_Ui/js/lib/events' +], function (_, EventsBus) { + 'use strict'; + + return _.extend({}, EventsBus, { + /** + * Tries to call specified method of a current component, + * otherwise delegates attempt to its' children. + * + * @param {String} target - Name of the method. + * @param [...] Arguments that will be passed to method. + * @returns {*} Result of the method calls. + */ + delegate: function (target) { + var args = _.toArray(arguments); + + target = this[target]; + + if (_.isFunction(target)) { + return target.apply(this, args.slice(1)); + } + + return this._delegate(args); + }, + + /** + * Calls 'delegate' method of all of it's children components. + * @private + * + * @param {Array} args - An array of arguments to pass to the next delegation call. + * @returns {Array} An array of delegation resutls. + */ + _delegate: function (args) { + var result; + + result = this.elems.map(function (elem) { + return elem.delegate.apply(elem, args); + }); + + return _.flatten(result); + }, + + /** + * Overrides 'EventsBus.trigger' method to implement events bubbling. + * + * @param {String} name - Name of the event. + * @param [...] Any number of arguments that should be to the events' handler. + * @returns {Boolean} False if event bubbling was canceled. + */ + trigger: function () { + var args = _.toArray(arguments), + bubble = EventsBus.trigger.apply(this, args), + result; + + if (!bubble) { + return false; + } + + this.containers.forEach(function (parent) { + result = parent.trigger.apply(parent, args); + + if (result === false) { + bubble = false; + } + }); + + return !!bubble; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/data_provider.js b/app/code/Magento/Ui/view/base/web/js/lib/data_provider.js deleted file mode 100644 index 281f6afa6a5fa379063368469064c96d19556041..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/data_provider.js +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - './rest', - 'Magento_Ui/js/lib/storage/index', - 'Magento_Ui/js/lib/class', - 'Magento_Ui/js/lib/events' -], function(_, Rest, storages, Class, EventsBus) { - 'use strict'; - - var defaults = { - stores: ['config', 'meta', 'data', 'params', 'dump'] - }; - - var DataProvider = Class.extend({ - /** - * Initializes DataProvider instance. - * @param {Object} settings - Settings to initialize object with. - */ - initialize: function(settings) { - _.extend(this, defaults, settings); - - this.initStorages() - .initClient(); - }, - - /** - * Creates instances of storage objects. - * @returns {DataProvider} Chainable. - */ - initStorages: function() { - var storage, - config; - - this.stores.forEach(function(store) { - storage = storages[store]; - config = this[store]; - - this[store] = new storage(config); - }, this); - - return this; - }, - - /** - * Creates instances of a REST client. - * @returns {DataProvider} Chainable. - */ - initClient: function() { - var config = this.config.get('client'); - - this.client = new Rest(config); - - this.client.on('read', this.onRead.bind(this)); - - return this; - }, - - /** - * Tries to retrieve data from server using REST client. - * Allways attaches cached parameters to request. - * @param {Object} [options] - Additional paramters to be attached. - * @returns {DataProvider} Chainable. - */ - refresh: function(options) { - var stored = this.params.get(), - params = _.extend({}, stored, options || {}); - - this.trigger('beforeRefresh'); - this.client.read(params); - - return this; - }, - - /** - * Updates list of storages with a specified data. - * @param {Object} data - Data to update storages with. - * @returns {DataProvider} Chainable. - */ - updateStorages: function(data) { - var value; - - this.stores.forEach(function(store) { - value = data[store]; - - if(value){ - this[store].set(value); - } - }, this); - - return this; - }, - - /** - * Callback method that fires when REST client - * will resolve requets to the server. - * @param {Object} result - Server response. - */ - onRead: function(result) { - result = { - data: result.data - }; - - this.updateStorages(result) - .trigger('refresh', result); - } - }, EventsBus); - - return DataProvider; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/deferred_events.js b/app/code/Magento/Ui/view/base/web/js/lib/deferred_events.js deleted file mode 100644 index 3b9dbd90425927e8d82a83fddbaa47930eca01d8..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/deferred_events.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'jquery', - './events' -], function ($, EventBus) { - 'use strict'; - - var events = {}; - - function isResolved(promise) { - return promise.state() === 'resolved'; - }; - - function toArray(obj, from) { - return Array.prototype.slice.call(obj, from || 0); - }; - - function on(context, name, callback) { - return EventBus.on.call(context, name, callback); - }; - - function trigger(name) { - return EventBus.trigger.apply(this, toArray(arguments)); - }; - - function getStorage(name) { - return events[name] || {}; - }; - - function getCallbacks(name) { - var storage = getStorage(name); - return storage.callbacks || []; - }; - - return { - when: function (name, callback) { - var storage = events[name] = getStorage(name), - callbacks = storage.callbacks = getCallbacks(name), - promise = storage.promise = storage.promise || $.Deferred(), - args = toArray(arguments), - resolveArgs; - - if (isResolved(promise)) { - return on(this, name, callback); - } - - if (~!callbacks.indexOf(callback)) { - callbacks.push(callback); - } - - promise.done(function () { - - callback.apply(this, arguments); - on(this, name, callback); - - }.bind(this)); - - return this; - }, - - resolve: function (name) { - var args = toArray(arguments, 1), - storage = events[name] = getStorage(name), - promise = storage.promise = storage.promise || $.Deferred(); - - if (isResolved(promise)) { - return trigger.bind(this, name).apply(this, args); - } - - promise.resolve.apply(promise, args); - - return this; - } - } -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/events.js b/app/code/Magento/Ui/view/base/web/js/lib/events.js index 00cb42852122575ecfb5a565f69d02e42432956d..7a8be3f5ad51a81ae69b5f2286978da3ed45b73a 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/events.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/events.js @@ -4,7 +4,7 @@ */ define([ 'underscore' -], function(_) { +], function (_) { 'use strict'; function addHandler(events, ns, callback, name) { @@ -20,19 +20,19 @@ define([ return name ? events[name] : events; } - function keepHandler(ns, handler){ - if(!ns){ + function keepHandler(ns, handler) { + if (!ns) { return false; } return handler.ns !== ns; } - function trigger(handlers, args){ - var bubble = true, + function trigger(handlers, args) { + var bubble = true, callback; - handlers.forEach(function(handler){ + handlers.forEach(function (handler) { callback = handler.callback; if (callback.apply(null, args) === false) { @@ -46,10 +46,9 @@ define([ return { /** * Calls callback when name event is triggered. - * @param {String} events - * @param {Function} callback - * @param {Function} ns - * @return {Object} reference to this + * @param {String} events + * @param {Function} callback + * @return {Object} reference to this */ on: function (events, callback, ns) { var storage = getEvents(this), @@ -69,20 +68,20 @@ define([ }, /** - * Removed callback from listening to target events + * Removed callback from listening to target event * @param {String} ns * @return {Object} reference to this */ off: function (ns) { var storage = getEvents(this), - filter = keepHandler.bind(null, ns); + filter = keepHandler.bind(null, ns); _.each(storage, function (handlers, name) { handlers = handlers.filter(filter); handlers.length ? - (storage[name] = handlers) : - (delete storage[name]); + storage[name] = handlers : + delete storage[name]; }); return this; @@ -95,9 +94,13 @@ define([ */ trigger: function (name) { var handlers = getEvents(this, name), - args = _.toArray(arguments).slice(1); + args = _.toArray(arguments).slice(1); + + if (_.isUndefined(handlers)) { + return true; + } - return _.isUndefined(handlers) || trigger(handlers, args); + return trigger(handlers, args); } }; }); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/date.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/date.js deleted file mode 100644 index ae14f38dd4d5f873641e5d919e2a36063a2e6699..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/date.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'ko', - 'moment', - 'jquery', - 'date-format-normalizer' -], function(ko, moment, $, convert) { - 'use strict'; - - ko.bindingHandlers.date = { - - /** - * Reads passed date and format from valueAccessor, uses convert function to format it. - * Writes date to el.innerText using jQuery - * @param {HTMLElement} el - Element, that binding is applied to - * @param {Function} valueAccessor - Function that returns value, passed to binding - */ - init: function(element, valueAccessor) { - var config = valueAccessor(), - format = convert(config.format), - date = moment(config.value).format(format); - - $(element).text(date); - } - }; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js index ec2823c793be641c03c0bef8f3acd901532e1756..843c126b663413058238b86dc03e5f82d2622f14 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js @@ -9,6 +9,14 @@ define([ ], function (ko, $) { 'use strict'; + function clickWrapper(elem, callback, e) { + var target = e.target; + + if (target !== elem && !elem.contains(target)) { + callback(); + } + } + ko.bindingHandlers.outerClick = { /** @@ -19,15 +27,17 @@ define([ * @param {Object} viewModel - reference to viewmodel */ init: function (element, valueAccessor, allBindings, viewModel) { - var callback = valueAccessor(); + var callback = valueAccessor(), + wrapper; callback = callback.bind(viewModel); + wrapper = clickWrapper.bind(null, element, callback); - $(document).on('click', callback); + $(document).on('click', wrapper); ko.utils.domNodeDisposal.addDisposeCallback(element, function () { - $(document).off('click', callback); + $(document).off('click', wrapper); }); } - } -}); \ No newline at end of file + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js index b8c32c121da6aa20930c724b511cc6084cb405ee..a2e303c11fe436872229169724caf8459b3fc60d 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js @@ -6,12 +6,10 @@ define([ 'ko', './template/engine', - './bind/date', './bind/scope', './bind/datepicker', './bind/stop_propagation', './bind/outer_click', - './bind/class', './bind/keyboard', './bind/optgroup', './extender/observable_array' diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/scope.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/scope.js deleted file mode 100644 index 65ee522bc2af1301ee2c3ca6726765546c581a6b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/scope.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'ko', - 'underscore', - '../class', - './initialize' -], function(ko, _, Class) { - 'use strict'; - - /** - * Wrapper for ko.observable and ko.observableArray. - * Assignes one or another ko property to obj[key] - * @param {Object} obj - object to store property to - * @param {String} key - key - * @param {*} value - initial value of observable - */ - function observe(obj, key, value){ - var method = Array.isArray(value) ? 'observableArray' : 'observable'; - - obj[key] = ko[method](value); - } - - return Class.extend({ - - /** - * If 2 params passed, path is considered as key. - * Else, path is considered as object. - * Assignes props to this based on incoming params - * @param {Object|String} path - * @param {*} value - */ - observe: function(path, value) { - var type = typeof path; - - if(arguments.length === 1){ - if(type === 'string'){ - path = path.split(' '); - } - - if(Array.isArray(path)){ - path.forEach(function(key){ - observe(this, key, this[key]); - }, this); - } - else if(type==='object'){ - _.each(path, function(value, key){ - observe(this, key, value); - }, this); - } - } - else if(type === 'string') { - observe(this, path, value); - } - - return this; - }, - - /** - * Reads it's params from provider and stores it into its params object - * @return {Object} reference to instance - */ - pushParams: function(){ - var params = this.params, - provider = this.provider.params, - data = {}; - - params.items.forEach(function(name) { - data[name] = this[name](); - }, this); - - provider.set(params.dir, data); - - return this; - }, - - /** - * Loops over params.items and writes it's corresponding {key: value} - * pairs to this as observables. - * @return {Object} reference to instance - */ - pullParams: function(){ - var params = this.params, - provider = this.provider.params, - data = provider.get(params.dir); - - params.items.forEach(function(name) { - this[name](data[name]); - }, this); - - return this; - }, - - /** - * Calls pushParams and calls refresh on this.provider - */ - reload: function() { - this.pushParams() - .provider.refresh(); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/template/engine.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/template/engine.js index eee3e1c6c08d2f8c0c7bc0948eab8e06e0dc3883..647cc2b985972513ce70f29d6b68d0774cb3a52d 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/template/engine.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/ko/template/engine.js @@ -5,9 +5,8 @@ define([ 'ko', './observable_source', - '../../renderer/renderer', - 'mage/apply/main' -], function (ko, Source, Renderer, Mage) { + '../../renderer/renderer' +], function (ko, Source, Renderer) { 'use strict'; var sources = {}; @@ -27,7 +26,7 @@ define([ /** * Remote template engine class. Is used to be able to load remote templates via knockout template binding. */ - var RemoteTemplateEngine = function() {}; + var RemoteTemplateEngine = function () {}; var NativeTemplateEngine = ko.nativeTemplateEngine; RemoteTemplateEngine.prototype = new NativeTemplateEngine; @@ -42,9 +41,8 @@ define([ * @param {Object} options - options, passed to template binding * @return {TemplateSource} - object with methods 'nodes' and 'data'. */ - RemoteTemplateEngine.prototype.makeTemplateSource = function(template, templateDocument, options) { + RemoteTemplateEngine.prototype.makeTemplateSource = function (template, templateDocument, options) { var source, - extenders = options.extenders || [], templateId; if (typeof template === 'string') { @@ -55,9 +53,8 @@ define([ source = new Source(template); sources[templateId] = source; - Renderer.render(template, extenders).done(function(rendered) { + Renderer.render(template).done(function (rendered) { source.nodes(rendered); - Mage.apply(); }); } @@ -99,4 +96,4 @@ define([ }; return new RemoteTemplateEngine; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/loader.js b/app/code/Magento/Ui/view/base/web/js/lib/loader.js index 9949551220945a95b6b89ce08cfede0223be30ac..03d97b399d7130727a01ff43eb4264dfa3b82d72 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/loader.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/loader.js @@ -11,26 +11,17 @@ define([ /** * Formats path of type "path.to.template" to RequireJS compatible * @param {String} path - * @returns {String} - formatted template path + * @return {String} - formatted template path */ function formatTemplatePath(path) { return 'text!' + path.replace(/^([^\/]+)/g, '$1/template') + '.html'; } - /** - * Waits for all items in passed array of promises to resolve. - * @param {Array} promises - array of promises - * @returns {Deferred} - promise of promises to resolve - */ - function waitFor(promises) { - return $.when.apply($, promises); - } - /** * Removes license from incoming template * * @param {String} tmpl - * @returns {String} - template without license + * @return {String} - template without license */ function removeLicense(tmpl) { var regEx = /<!--[\s\S]*?-->/; @@ -44,7 +35,7 @@ define([ * Loads template by path, resolves promise with it if defined * * @param {String} path - * @params {Deferred} promise + * @param {Deferred} promise */ function load(path, promise) { require([path], function (template) { @@ -59,12 +50,11 @@ define([ * Loops over arguments and loads template for each. * @return {Deferred} - promise of templates to be loaded */ - loadTemplate: function () { - var isLoaded = $.Deferred(), - templates = _.toArray(arguments); + loadTemplate: function (source) { + var isLoaded = $.Deferred(); - waitFor(templates.map(this._loadTemplate)).done(function () { - isLoaded.resolve.apply(isLoaded, arguments); + this._loadTemplate(source).done(function (tmpl) { + isLoaded.resolve(tmpl); }); return isLoaded.promise(); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/mixins/loader.js b/app/code/Magento/Ui/view/base/web/js/lib/mixins/loader.js deleted file mode 100644 index 4e310b1ca86a992706cbc98941cf7d09075eae9e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/mixins/loader.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'Magento_Ui/js/lib/spinner' -], function (spinner) { - 'use strict'; - - return { - /** - * Activates spinner - * @return {Object} reference to instance - */ - lock: function() { - spinner.show(); - - return this; - }, - - /** - * Deactivates spinner - * @return {Object} reference to instance - */ - unlock: function() { - spinner.hide(); - - return this; - } - } -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/provider.js b/app/code/Magento/Ui/view/base/web/js/lib/provider.js index 66454fee11c9bf0b5cdba395fe36c320f183d173..dafb8ad304893a957e261fabb503af434a79fe30 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/provider.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/provider.js @@ -3,43 +3,92 @@ * See COPYING.txt for license details. */ define([ - 'jquery', - './data_provider', - 'Magento_Ui/js/lib/registry/registry' -], function($, DataProvider, registry) { + 'underscore', + 'mageUtils', + 'Magento_Ui/js/lib/class', + 'Magento_Ui/js/lib/events' +], function (_, utils, Class, EventsBus) { 'use strict'; - /** - * Merges passed settings with preset ajax properties - * @param {Object} settings - * @returns {Object} - mutated settings - */ - function getConfig(settings) { - var config = settings.config, - client = config.client = config.client || {}; - - $.extend(true, client, { - ajax: { - data: { - name: settings.name, - form_key: FORM_KEY - } - } - }); + function getStored(ns) { + var stored = localStorage.getItem(ns); - return settings; + return !_.isNull(stored) ? JSON.parse(stored) : {}; } - /** - * Creates new data provider and register it by settings.name - * @param {Object} settings - */ - function init(settings) { - var name = settings.name, - config = getConfig(settings); + function store(ns, property, data) { + var stored = getStored(ns); + + utils.nested(stored, property, data); - registry.set(name, new DataProvider(config)); + localStorage.setItem(ns, JSON.stringify(stored)); } - return init; -}); \ No newline at end of file + var Provider = _.extend({ + /** + * Initializes DataProvider instance. + * @param {Object} config - Settings to initialize object with. + */ + initialize: function (config) { + _.extend(this.data = {}, config); + + this.restore(); + + return this; + }, + + /** + * If path specified, returnes this.data[path], else returns this.data + * @param {String} path + * @return {*} this.data[path] or simply this.data + */ + get: function (path) { + return utils.nested(this.data, path); + }, + + /** + * Sets value property to path and triggers update by path, passing result + * @param {String|*} path + * @param {String|*} value + * @return {Object} reference to instance + */ + set: function (path, value) { + var data = utils.nested(this.data, path), + diffs = utils.compare(data, value, path); + + utils.nested(this.data, path, value); + + diffs.changes.forEach(function (change) { + this.trigger(change.name, change.value, change); + }, this); + + _.each(diffs.containers, function (changes, name) { + this.trigger(name, changes); + }, this); + + return this; + }, + + restore: function () { + var stored = getStored(this.data.dataScope); + + utils.extend(this.data, stored); + }, + + store: function (property, data) { + if (!data) { + data = this.get(property); + } else { + this.set(property, data); + } + + store(this.data.dataScope, property, data); + }, + + remove: function (path) { + utils.nestedRemove(this.data, path); + } + }, EventsBus); + + return Class.extend(Provider); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js b/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js index 21969f43dc8529e879a2193ee4b70892b5136a42..cf4b3b13d10936ae149320b54ec767079a0e8241 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils' + 'mageUtils' ], function (_, utils) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js b/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js index db002ca2a3cf703b238b514691c7c74b4534e32d..8c0448aaa49b38d71181d480df436fb3949b392e 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js @@ -3,10 +3,10 @@ * See COPYING.txt for license details. */ define([ - 'mage/utils', + 'mageUtils', './storage', './events' -], function (utils, Storage, Events) { +], function(utils, Storage, Events) { 'use strict'; function Registry() { @@ -20,21 +20,22 @@ define([ /** * Retrieves data from registry. * - * @param {(String|Array)} elems - An array of elements' names or - * a string of names divided by spaces. - * @param {Function} [callback] - Callback function that will be triggered + * @params {(String|Array)} elems - + * An array of elements' names or a string of names divided by spaces. + * @params {Function} [callback] - + * Callback function that will be triggered * when all of the elements are registered. * @returns {Array|*|Undefined} * Returns either an array of elements * or an element itself if only is requested. * If callback function is specified then returns 'undefined'. */ - get: function (elems, callback) { + get: function(elems, callback) { var records; elems = utils.stringToArray(elems) || []; - if (typeof callback == 'function') { + if (typeof callback !== 'undefined') { this.events.wait(elems, callback); } else { records = this.storage.get(elems); @@ -45,11 +46,12 @@ define([ } }, - /** + + /** * Sets data to registry. * - * @param {String} elem - Elements' name. - * @param {*} value - Value that will be assigned to the element. + * @params {String} elems - Elements' name. + * @params {*} value - Value that will be assigned to the element. * @returns {registry} Chainable. */ set: function (elem, value) { @@ -61,8 +63,8 @@ define([ /** * Removes specified elements from a storage. - * @param {(String|Array)} elems - An array of elements' names or - * a string of names divided by spaces. + * @params {(String|Array)} elems - + * An array of elements' names or a string of names divided by spaces. * @returns {registry} Chainable. */ remove: function (elems) { @@ -76,8 +78,8 @@ define([ /** * Checks whether specified elements has been registered. * - * @param {(String|Array)} elems - An array of elements' names or - * a string of names divided by spaces. + * @params {(String|Array)} elems - + * An array of elements' names or a string of names divided by spaces. * @returns {Boolean} */ has: function (elems) { diff --git a/app/code/Magento/Ui/view/base/web/js/lib/registry/storage.js b/app/code/Magento/Ui/view/base/web/js/lib/registry/storage.js index bf701810285e24c5589f2a1f28bb39b9f56c0f55..f7d95da8b4f622aea4d1e315dc7b6ae2d462a2ad 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/registry/storage.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/registry/storage.js @@ -19,17 +19,12 @@ define([], function () { * @returns {Array} Array of values. */ get: function (elems) { - var data = this.data, - record; + var data = this.data; elems = elems || []; return elems.map(function (elem) { - record = data[elem]; - - if (record) { - return record.value; - } + return data[elem]; }); }, @@ -41,10 +36,9 @@ define([], function () { * returns {storage} Chainable. */ set: function (elem, value) { - var data = this.data, - record = data[elem] = data[elem] || {}; + var data = this.data; - record.value = value; + data[elem] = value; return this; }, diff --git a/app/code/Magento/Ui/view/base/web/js/lib/renderer/overrides.js b/app/code/Magento/Ui/view/base/web/js/lib/renderer/overrides.js deleted file mode 100644 index 4569fc6d34d13b4f021e475c4a12e4ad09d3c0af..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/renderer/overrides.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define(['jquery'], function($) { - 'use strict'; - - return { - - /** - * Removes passed html element. - * @param {HTMLElement} oldPart - html element to remove - */ - remove: function(oldPart) { - $(oldPart).remove(); - }, - - /** - * Picks last node of newParts and replaces oldPart node with it. - * @param {HTMLElement} oldPart - html element to replace - * @param {Array} newParts - array of html elements - */ - replace: function(oldPart, newParts) { - var newPart = _.last(newParts); - - $(oldPart).replaceWith(newPart); - }, - - /** - * Picks last node of newParts and replaces oldPart node with it's children. - * @param {HTMLElement} oldPart - html element to replace - * @param {HTMLElement} newParts - array of html elements - */ - body: function(oldPart, newParts) { - var newPart = _.last(newParts); - - $(oldPart).replaceWith(newPart.children); - }, - - /** - * Picks the last item of newParts array and overides oldPart's html attributes with ones of it's own. - * @param {HTMLElement} oldPart - target html element to update - * @param {Array} newParts - array of html elements to get attributes from - */ - update: function(oldPart, newParts) { - var newPart = _.last(newParts); - - var attributes = newPart.attributes; - var value, name; - - _.each(attributes, function(attr) { - value = attr.value; - name = attr.name; - - if (attr.name.indexOf('data-part') !== -1) { - return; - } - - $(oldPart).attr(name, value); - }); - }, - - /** - * Prepends oldPart with each html element's children from newParts array. - * @param {HTMLElement} oldPart - html element to prepend to - * @param {Array} newParts - array of html elements to get attributes from - */ - prepend: function(oldPart, newParts) { - newParts.forEach(function (node) { - $(oldPart).prepend(node.children); - }); - }, - - /** - * Appends oldPart with each html element's children from newParts array. - * @param {HTMLElement} oldPart - html element to append to - * @param {Array} newParts - array of html elements to get attributes from - */ - append: function(oldPart, newParts) { - newParts.forEach(function (node) { - $(oldPart).append(node.children); - }); - }, - - /** - * @return {Array} - array of strings representing available set of actions - */ - getActions: function() { - return 'replace remove body update append prepend'.split(' '); - } - }; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/renderer/renderer.js b/app/code/Magento/Ui/view/base/web/js/lib/renderer/renderer.js index 3237dfd4ffef689634a37860f0a10941c5ab2c0e..9da1291111f07e421eb1f41ca8b1ee6aa67bf1bb 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/renderer/renderer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/renderer/renderer.js @@ -4,53 +4,28 @@ */ define([ '../loader', - './overrides', 'jquery', 'underscore' -], function(loader, overrides, $, _) { +], function (loader, $, _) { 'use strict'; return { - /** * Renders template and it's extenders using this._parse function. * Loads all extenders then merges them and wraps into div[data-template-extend="parent"] where parent is target template. * If no extenders provider, simply loads target template and passes execution to _parse. * @param {String} template - string, representing path to core template and it's extenders. - * @param {Array} extenders - array of strings - * @return {Deferred} - Promise of template to be rendered. Is being resolved with array of HTML elements. + * @returns {Deferred} - Promise of template to be rendered. Is being resolved with array of HTML elements. */ - render: function (template, extenders) { + render: function (template) { var isRendered = $.Deferred(), - parent = template, - - extenders = extenders || [], - extendersToLoad = [], - extendersHtml = '', - resolve = isRendered.resolve.bind(isRendered), loadTemplate = this._load.bind(this), parseTemplate = this._parse.bind(this); - if (extenders.length) { - - loadTemplate.apply(this, extenders).done(function () { - - toArray(arguments).forEach(function (chunk) { - extendersHtml += chunk; - }); - - extendersHtml = '<div data-template-extend="' + parent+ '">' + extendersHtml + '</div>'; - - parseTemplate(extendersHtml).done(resolve); - - }); - } else { - - loadTemplate(parent) - .then(parseTemplate) - .done(resolve); - } + loadTemplate(template) + .then(parseTemplate) + .done(resolve); return isRendered.promise(); }, @@ -73,186 +48,8 @@ define([ * @param {String} rawHtml - loaded raw text (html) * @return {Deferred} - Promise of template to be parsed. Is being resolved with array of HTML elements. */ - _parse: function(rawHtml) { - var templatePath, - templateContainer, - extendNodes, - templatesToRender = [], - extendPointsToRender = []; - - templateContainer = document.createElement('div'); - - wrap(toArray($.parseHTML(rawHtml)), templateContainer); - - extendNodes = getExtendNodesFrom(templateContainer); - templatesToRender = extendNodes.map(extractTemplatePath, this) - extendPointsToRender = templatesToRender.map(this.render, this); - - return waitFor(extendPointsToRender).then(function() { - var correspondingExtendNode, - container, - newParts = [], - args = toArray(arguments); - - args.forEach(function(renderedNodes, idx) { - container = document.createElement('div'); - wrap(renderedNodes, container); - - correspondingExtendNode = extendNodes[idx]; - newParts = this._buildPartsMapFrom(correspondingExtendNode); - - $(correspondingExtendNode).empty(); - - this._overridePartsOf(container, newParts) - .replace(correspondingExtendNode); - - }, this); - - return toArray(templateContainer.childNodes); - }.bind(this)); - }, - - /** - * Builds parst map from HTML element by looking for all available override actions selectors. - * @param {HTMLElement} container - container to look up for new parts declarations - * @return {Object} - Map of parts to apply. E.g. { toolbar: { replace: [HTMLElement1, HTMLElement2], append: [HTMLElement3] } } - */ - _buildPartsMapFrom: function(container) { - var partsMap = {}, - actionNodes, - partSelector, - targetPart, - actions = overrides.getActions(); - - actions.forEach(function(action) { - partSelector = createActionSelectorFor(action); - actionNodes = toArray(container.querySelectorAll(partSelector)); - - actionNodes.forEach(function(node) { - targetPart = node.getAttribute('data-part-' + action); - - if (!partsMap[targetPart]) { - partsMap[targetPart] = {}; - } - - targetPart = partsMap[targetPart]; - - if (!targetPart[action]) { - targetPart[action] = []; - } - - targetPart[action].push(node); - }); - }); - - return partsMap; - }, - - /** - * Loops over newParts map and invokes override actions for each found. - * @param {HTMLElement} template - container to look for parts to be overrided by new ones. - * @param {Object} newParts - the result of _buildPartsMapFrom method. - * @return {Object} - */ - _overridePartsOf: function(template, newParts) { - var oldElement; - - _.each(newParts, function(actions, partName) { - _.each(actions, function(newElements, action) { - - oldElement = template.querySelector(createPartSelectorFor(partName)); - overrides[action]( - oldElement, - newElements - ); - - }); - }); - - return { - - /** - * Replaces extendNode with the result of overrides - * @param {HTMLElement} extendNode - initial container of new parts declarations - */ - replace: function(extendNode) { - $(extendNode).replaceWith(template.childNodes); - } - } + _parse: function (rawHtml) { + return _.toArray($.parseHTML(rawHtml)); } }; - - /** - * Extracts template path from node by [data-part-extend] attribute - * @param {HTMLElement} node - node to look up for [data-part-extend] attr - * @return {String} - value of [data-part-extend] attribute - */ - function extractTemplatePath(node) { - return node.getAttribute('data-template-extend'); - } - - /** - * Looks up for [data-template-extend] selector in container. - * @param {HTMLElement} container - node to lookup - * @return {Array} - array of found HTML elements - */ - function getExtendNodesFrom(container) { - return toArray(container.querySelectorAll('[data-template-extend]')) - } - - /** - * Checks if passed object has keys. - * @param {Object} object - target object - * @return {Boolean} - true, if object has no keys - */ - function isEmpty(object) { - return !Object.keys(object).length; - } - - /** - * Wraps nodes into container - * @param {Array} nodes - array of nodes - * @param {HTMLElement} container - target container - */ - function wrap(nodes, container) { - nodes.forEach(function (node) { - container.appendChild(node); - }); - } - - /** - * Creates action selector. - * @param {String} action - * @return {String} - Action selector - */ - function createActionSelectorFor(action) { - return '[data-part-' + action + ']'; - } - - /** - * Creates data-part selector. - * @param {String} part - * @return {String} - Part selector - */ - function createPartSelectorFor(part) { - return '[data-part="' + part + '"]'; - } - - /** - * Converts arrayLikeObject to array - * @param {Object|Array} arrayLikeObject - target - * @return {Array} - result array - */ - function toArray(arrayLikeObject) { - return Array.prototype.slice.call(arrayLikeObject); - } - - /** - * Waits for all items in passed array of promises to resolve. - * @param {Array} promises - array of promises - * @return {Deferred} - promise of promises to resolve - */ - function waitFor(promises) { - return $.when.apply(this, promises); - } -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/request_builder.js b/app/code/Magento/Ui/view/base/web/js/lib/request_builder.js deleted file mode 100644 index a70d13af32c6450cce6825bd10e81218db2a2055..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/request_builder.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/** - * @returns {Function} Request builder function. - */ -define([ - 'Magento_Ui/js/lib/utils' -], function(utils) { - 'use strict'; - - /** - * @param {String} - name of params set - * @param {Object} - params to convert - * @returns {String} - concatenated name/params pairs by custom logic and separator - * @private - */ - function parseObject(name, value) { - var key, - result = []; - - for (key in value) { - result.push(name + '[' + key + ']' + '=' + value[key]) - } - - return result.join('&'); - } - - /** - * @param {String} - name of property - * @param {String} - corresponding value - * @returns {String} - concatenated params by separator "=" - * @private - */ - function parseValue(name, value) { - return name + '=' + value; - } - - /** - * Extracts sorting parameters from object and returns string representation of it. - * @param {Object} param - Sorting parameters object, e.g. { field: 'field_to_sort', dir: 'asc' }. - * @returns {String} - Chunk of url string that represents sorting params - * @private - */ - function extractSortParams(params) { - var result, - sorting = params.sorting; - - if (typeof sorting === 'undefined') { - return ''; - } - - result = '/sort/' + sorting.field + '/dir/' + sorting.direction; - - delete params.sorting; - - return result; - } - - /** - * Extracts pager parameters from an object and returns it's string representation. - * @param {Object} params which contains "paging" params object. - * @returns {String} - Chunk of url string that represents pager params - * @private - */ - function extractPagerParams(params) { - var result, - paging = params.paging; - - if (typeof paging === 'undefined') { - return ''; - } - - result = '/limit/' + paging.pageSize + '/page/' + paging.current; - - delete params.paging; - - return result; - } - - /** - * Formats filter data according to the type of it's value. - * @param {Object} filter - filter object to format. - * @returns {String} - Chunk of url string that represents filter's params - * @private - */ - function formatFilter(filter) { - var name = filter.field, - value = filter.value; - - return typeof value !== 'object' ? - parseValue(name, value) : - parseObject(name, value); - } - - /** - * Formats and assembles filter data. - * @param {Object} params - object containing "filter" array. - * @returns {String} - Chunk of url string that represents filters - * @private - */ - function extractFilterParams(params) { - var filters, - result; - - filters = params.filter; - - if (typeof filters === 'undefined' || !filters.length) { - return ''; - } - - result = filters.map(formatFilter).join('&'); - - result = '/filter/' + utils.btoa(encodeURI(result)); - - delete params.filter; - - return result; - } - - return function(root, params) { - var url, - lastChar; - - lastChar = root.charAt(root.length - 1); - - if (lastChar === '/') { - root = root.substr(0, root.length - 1); - } - - url = - root + - extractSortParams(params) + - extractPagerParams(params) + - extractFilterParams(params); - - return url; - }; - -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/rest.js b/app/code/Magento/Ui/view/base/web/js/lib/rest.js deleted file mode 100644 index 2c29c393ad314cc0ea2759fad20e0440a2c9d6f7..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/rest.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'jquery', - 'Magento_Ui/js/lib/utils', - 'Magento_Ui/js/lib/class', - 'Magento_Ui/js/lib/events', - './request_builder' -], function(_, $, utils, Class, EventsBus, requestBuilder) { - 'use strict'; - - var defaults = { - ajax: { - dataType: 'json' - } - }; - - return Class.extend({ - initialize: function(config) { - $.extend(true, this.config = {}, defaults, config); - }, - - /** - * Sends ajax request using params and config passed to it and calls this.config.onRead when done. - * @param {Object} params - request body params - * @param {Object} config - config to build url from - */ - read: function(params, config) { - config = this.createConfig(params, config); - - $.ajax(config) - .done(this.onRead.bind(this)); - }, - - /** - * Creates config for ajax call. - * @param {Object} params - request body params - * @param {Object} config - config to build url from - * @returns {Object} - merged config for ajax call - */ - createConfig: function(params, config) { - var baseConf; - - config = config || {}; - params = params || {}; - - baseConf = { - url: requestBuilder(this.config.root, params), - data: params - }; - - return $.extend(true, baseConf, this.config.ajax, config); - }, - - /** - * Callback of ajax call. - * Parses results and triggers read event; - * @param {Object|*} result - Result of ajax call. - */ - onRead: function(result){ - result = typeof result === 'string' ? - JSON.parse(result) : - result; - - this.trigger('read', result); - }, - - /** - * Submits data using utils.submitAsForm - * @param {Object} config - object containing ajax options - */ - submit: function(config){ - var ajax = this.config.ajax, - data = ajax.data || {}; - - _.extend(config.data, data); - - utils.submitAsForm(config); - } - }, EventsBus); - -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/spinner.js b/app/code/Magento/Ui/view/base/web/js/lib/spinner.js index 4a9eae7d96340bd74c59b178025686c14f601723..a610c194333530d7706ceb4c15fb368807e6acc8 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/spinner.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/spinner.js @@ -7,8 +7,8 @@ define([ ], function ($) { 'use strict'; - var selector = '[data-role="spinner"]', - spinner = $(selector); + var selector = '[data-role="spinner"]', + spinner = $(selector); return { show: function () { @@ -22,5 +22,5 @@ define([ get: function (id) { return $(selector + '[data-component="' + id + '"]'); } - } -}); \ No newline at end of file + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/dump.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/dump.js deleted file mode 100644 index 8c904764da3fde329e62aefac46849b762dc453e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/dump.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - './storage', - 'Magento_Ui/js/lib/deferred_events' -], function (Storage, DeferredEvents) { - return Storage.extend({}, DeferredEvents); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/index.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/index.js deleted file mode 100644 index ca58235fa19b4adbc060bc76bba9be29d4711b9e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/** - * Assembles storages returning storage mapping - */ -define([ - './storage', - './meta', - './dump' -], function(Storage, MetaStorage, DumpStorage){ - 'use strict'; - - return { - meta: MetaStorage, - params: Storage, - config: Storage, - data: Storage, - dump: DumpStorage - } -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/meta.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/meta.js deleted file mode 100644 index d3cee2931c4d68da898f7dc461c23c0ce7c7e761..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/meta.js +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - './storage' -], function(_, Storage) { - 'use strict'; - - /** - * Loops over first level of object looking for valueKey of typeof object values - * to be typeof object as well. Breaks loop on first entry on one. - * @param {Object} target - * @param {String} valueKey - complex to look for - * @return {Boolean} - */ - function hasComplexValue(target, valueKey) { - var result = false, - key, - object; - - - for (key in target) { - object = target[key]; - - if (typeof object === 'object' && typeof object[valueKey] === 'object') { - result = true; - break; - } - } - - return result; - } - - /** - * Recursively loops over object's properties and converts it to array ignoring keys. - * If typeof 'value' properties is 'object', creates 'items' property and assigns - * execution of nestedObjectToArray on 'value' to it. - * If typeof 'value' key is not an 'object', is simply writes an object itself to result array. - * @param {Object} obj - * @return {Array} result array - */ - function nestedObjectToArray(obj, valueKey) { - var target, - items = []; - - for (var prop in obj) { - - target = obj[prop]; - if (typeof target[valueKey] === 'object') { - - target.items = nestedObjectToArray(target[valueKey], valueKey); - delete target[valueKey]; - } - items.push(target); - } - - return items; - } - - return Storage.extend({ - - /** - * Initializes data prop based on data argument. - * Calls initFields and initColspan methods - * @param {Object} config - */ - initialize: function(data) { - this.data = data || {}; - - this.initFields() - .initColspan(); - }, - - /** - * Formats fields property to compatible format. - * Processes those. Assignes fiedls to data.fields. - * @return {Object} - reference to instance - */ - initFields: function(){ - var data = this.data, - fields = data.fields; - - fields = this._fieldsToArray(fields); - - fields.forEach(this._processField, this); - - data.fields = fields; - - return this; - }, - - /** - * Assigns data.colspan to this.getVisible().length - * @return {Object} - reference to instance - */ - initColspan: function(){ - var visible = this.getVisible(); - - this.data.colspan = visible.length; - - return this; - }, - - /** - * Assignes default params to field - * @param {Object} field - * @return {Object} reference to instance - */ - applyDefaults: function(field) { - var defaults = this.data.defaults; - - if (defaults) { - _.defaults(field, defaults); - } - - return this; - }, - - /** - * Format options based on those being nested - * @param {Object} field - * @return {Object} reference to instance - */ - formatOptions: function(field) { - var result, - options, - isNested; - - options = field.options; - - if (options) { - result = {}; - isNested = hasComplexValue(options, 'value'); - - if(isNested){ - result = nestedObjectToArray(options, 'value'); - } - else{ - _.each(options, function(option){ - result[option.value] = option.label; - }); - } - - field.options = result; - } - - return this; - }, - - /** - * Returns filted by visible property fields array. - * @return {Array} filted by visible property fields array - */ - getVisible: function(){ - var fields = this.data.fields; - - return fields.filter(function(field){ - return field.visible; - }); - }, - - /** - * Convertes fields object to array, assigning key to index property. - * @param {Object} fields - * @return {Array} array of fields - */ - _fieldsToArray: function(fields){ - return _.map(fields, function(field, id){ - field.index = id; - - return field; - }); - }, - - /** - * Calls applyDefaults and formatOptions on field - * @param {Object} field - */ - _processField: function(field){ - this.applyDefaults(field) - .formatOptions(field); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/storage.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/storage.js deleted file mode 100644 index e0075c746b5466e8d48e247ea3e9dd9eea7e0588..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/storage.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - '../class', - '../events', - 'mage/utils' -], function(_, Class, EventsBus, utils) { - 'use strict'; - - return Class.extend({ - - /** - * Inits this.data to incoming data - * @param {Object} data - */ - initialize: function(data) { - this.data = data || {}; - }, - - /** - * If path specified, returnes this.data[path], else returns this.data - * @param {String} path - * @return {*} this.data[path] or simply this.data - */ - get: function(path) { - return utils.nested(this.data, path); - }, - - /** - * Sets value property to path and triggers update by path, passing result - * @param {String|*} path - * @param {String|*} value - * @return {Object} reference to instance - */ - set: function(path, value){ - var result = this._override.apply(this, arguments); - - value = result.value; - path = result.path; - - this.trigger('update', value); - - if (path) { - this.trigger('update:' + path, value); - } - - return this; - }, - - remove: function (path) { - utils.nestedRemove(this.data, path); - - return this; - }, - - /** - * Assignes props to this.data based on incoming params - * @param {String|*} path - * @param {*} value - * @return {Object} - */ - _override: function(path, value) { - if (arguments.length > 1) { - utils.nested(this.data, path, value); - } else { - value = path; - path = false; - - this.data = value; - } - - return { - path: path, - value: value - }; - } - - }, EventsBus); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/utils.js b/app/code/Magento/Ui/view/base/web/js/lib/utils.js deleted file mode 100644 index dcc7c65e3255f6663273451b11916e8bc8c43f60..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/utils.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'mage/utils' -], function(_, utils) { - 'use strict'; - - var utils = {}, - atobSupport, - btoaSupport; - - atobSupport = typeof atob === 'function'; - btoaSupport = typeof btoa === 'function'; - - /** - * Base64 encoding/decoding methods. - * First check for native support. - */ - if( btoaSupport && atobSupport ){ - _.extend(utils, { - atob: function(input){ - return window.atob(input); - }, - - btoa: function(input){ - return window.btoa(input); - } - }); - } - else{ - _.extend(utils, { - atob: function(input){ - return Base64.decode(input) - }, - - btoa: function(input){ - return Base64.encode(input); - } - }); - } - - /** - * Submits specified data as a form object. - * @param {Object} params - Parameters of form. - */ - utils.submitAsForm = function(params){ - var form, - field; - - form = document.createElement('form'); - - form.setAttribute('method', params.method); - form.setAttribute('action', params.action); - - _.each(params.data, function(value, name){ - field = document.createElement('input'); - - if(typeof value === 'object'){ - value = JSON.stringify(value); - } - - field.setAttribute('name', name); - field.setAttribute('type', 'hidden'); - - field.value = value; - - form.appendChild(field); - }); - - document.body.appendChild(form); - - form.submit(); - }; - - return utils; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/filter.js b/app/code/Magento/Ui/view/base/web/js/listing/filter.js deleted file mode 100644 index 95f58dde2c123d688562ca465e4973f51d57b909..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/filter.js +++ /dev/null @@ -1,271 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'Magento_Ui/js/lib/ko/scope', - 'Magento_Ui/js/lib/component' -], function(_, Scope, Component) { - 'use strict'; - - var BASE_PATH = 'Magento_Ui/js/listing/filter'; - - var defaults = { - types: { - filter_input: BASE_PATH + '/input', - filter_select: BASE_PATH + '/select', - filter_range: BASE_PATH + '/range', - filter_date: BASE_PATH + '/date' - } - }; - - var Filter = Scope.extend({ - /** - * Initializes instance properties - * @param {Object} config - Filter component configuration - */ - initialize: function(config) { - _.extend(this, config); - - this.initObservable() - .loadControls(); - }, - - /** - * Callback method that proceeds initialization of filter component. - */ - proceed: function () { - this.extractFields() - .initFilters(); - }, - - /** - * Initiates loading of filters constructors. - */ - loadControls: function () { - var coreTypes = defaults.types, - paths, - types; - - types = _.map(this.types, function (config, type) { - config.name = type; - - if(!config.control){ - config.control = coreTypes[type]; - } - - return config; - }); - - paths = _.pluck(types, 'control'); - - require(paths, this.onControlsLoaded.bind(this, types)); - }, - - /** - * Initializes observable properties of instance. - * @returns {Filter} Chainbale. - */ - initObservable: function(){ - this.observe({ - isVisible: false, - active: [], - filters: [] - }); - - return this; - }, - - /** - * Filters filterable fields and stores them to this.fields - * @returns {Filter} Chainbale. - */ - extractFields: function () { - var provider = this.provider.meta, - fields = provider.getVisible(); - - this.fields = fields.filter(function (field) { - return field.filterable; - }); - - return this; - }, - - /** - * Initializes filters by creating instances of - * corresponding classes found in controls by filter type. - * @returns {Filter} Chainbale. - */ - initFilters: function () { - var controls = this.types, - config, - type, - filters, - control; - - filters = this.fields.map(function (field) { - type = (field.filter_type || field.input_type); - config = controls && controls[type]; - control = config.constr; - - field.type = type; - field.module = config.module || 'ui'; - - return new control(field, config); - }, this); - - this.filters(filters); - - return this; - }, - - /** - * Extracts an array of non-empty filters. - * @returns {Array} Array of non-empty filters - */ - getNotEmpty: function(){ - return this.filters().filter(function(filter){ - return !filter.isEmpty(); - }); - }, - - /** - * Writes the result of getNotEmpty to active observable. - * @returns {Filter} Chainbale. - */ - findActive: function(){ - this.active(this.getNotEmpty()); - - return this; - }, - - /** - * Returns an array filters' data. - * @param {Boolean} [all=false] - - Whether to extract data from all of the filters - or from only the active ones. - * @returns {Array} Array of filters' data. - */ - getData: function(all){ - var filters; - - filters = all ? this.filters() : this.active(); - - return filters.map(function(filter){ - return filter.dump(); - }); - }, - - /** - * Clears data of all filters or of specified one. - * @param {Object} [filter] - If specified, clears data only of this filter. - * @returns {Filter} Chainbale. - */ - clearData: function(filter){ - var active = this.active; - - if(filter){ - filter.reset(); - - active.remove(filter); - } - else{ - this.filters().forEach(function (filter) { - filter.reset(); - }); - - active.removeAll(); - } - - return this; - }, - - /** - * Updates an array of active filters - * and reloads data provider with new filtering parameters. - * @returns {Filter} Chainbale. - */ - apply: function () { - this.findActive() - .reload(); - - return this; - }, - - /** - * Clears filters and updates data provider with new filtering parameters. - * @param {Object} [filter] - If specified then clears only this filter. - * @returns {Filter} Chainbale. - */ - reset: function(filter){ - this.clearData(filter) - .reload(); - - return this; - }, - - /** - * Sets set of params to storage. - * @param {*} action - data to set to storage params - * @returns {Filter} Chainbale. - */ - pushParams: function() { - var params = this.provider.params; - - params.set('filter', this.getData()); - - return this; - }, - - /** - * @description Toggles isVisible observable property - */ - toggle: function () { - this.isVisible(!this.isVisible()); - }, - - /** - * @description Sets isVisible observable property to false - */ - close: function () { - this.isVisible(false); - }, - - /** - * Resets specified filter using reset method - * @param {Object} filter - filter to reset - */ - onClear: function(filter) { - return this.reset.bind(this, filter); - }, - - /** - * Callback that fires when all of the filters constructors has been loaded. - * @param {Array} controlsMap - An array of availbale filter types and theirs configuration. - */ - onControlsLoaded: function (controlsMap) { - var controls = Array.prototype.slice.call(arguments, 1), - types = {}, - control; - - controls.forEach(function (constr, idx) { - control = controlsMap[idx]; - - delete control.control; - - control.constr = constr; - - types[control.name] = control; - }); - - this.types = types; - - this.proceed(); - } - }); - - return Component({ - constr: Filter - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/filter/abstract.js b/app/code/Magento/Ui/view/base/web/js/listing/filter/abstract.js deleted file mode 100644 index bf52c36dd9aa4478fa96a7cef7ce000e2bb82fe5..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/filter/abstract.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'Magento_Ui/js/lib/ko/scope', - 'underscore' -], function (Scope, _) { - 'use strict'; - - return Scope.extend({ - - /** - * Extends instance with data passed. - * @param {Object} data - Item of "fields" array from grid configuration - * @param {Object} config - Filter configuration - */ - initialize: function (data, config) { - _.extend(this, data); - this.config = config; - - this.observe('output', ''); - }, - - isEmpty: function () {}, - - /** - * Returns alias for filter item template - * @return {String} - */ - getTemplate: function () { - return this.module + '/filter/' + this.type; - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/filter/date.js b/app/code/Magento/Ui/view/base/web/js/listing/filter/date.js deleted file mode 100644 index bff6c90fc63f7727483217c47ec08ddc1e88b964..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/filter/date.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - './range' -], function (Range) { - 'use strict'; - - return Range; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/filter/filters.js b/app/code/Magento/Ui/view/base/web/js/listing/filter/filters.js deleted file mode 100644 index 147b2b1d508e7a4d8c745fa7cf1bafd65880c0fd..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/filter/filters.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/** Assembles available filter controls and returns it's mapping. */ -define([ - './input', - './select', - './range' -], function (InputControl, SelectControl, RangeControl) { - 'use strict'; - - return { - input: InputControl, - select: SelectControl, - date: RangeControl, - range: RangeControl, - store: SelectControl - } -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/filter/input.js b/app/code/Magento/Ui/view/base/web/js/listing/filter/input.js deleted file mode 100644 index fdd6735151fff7d92e91d6755dcce103f63e10ab..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/filter/input.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - './abstract', - 'underscore' -], function (AbstractControl, _) { - 'use strict'; - - return AbstractControl.extend({ - - /** - * Invokes initialize method of parent class and initializes observable properties of instance. - * @param {Object} data - Item of "fields" array from grid configuration - * @param {Object} config - Filter configuration - */ - initialize: function (data) { - this.constructor.__super__.initialize.apply(this, arguments); - - this.observe('value', ''); - }, - - /** - * Returnes true if this.value is falsy - * @return {Boolean} true if this.value is falsy, false otherwise - */ - isEmpty: function(){ - return !this.value(); - }, - - /** - * Returns this.value(). Is used for displaying on UI. - * @return {[type]} [description] - */ - display: function(){ - return this.value(); - }, - - /** - * Returns dump of instance's current state - * @returns {Object} - object which represents current state of instance - */ - dump: function () { - this.output( this.display() ); - - return { - field: this.index, - value: this.value() - }; - }, - - /** - * Resets state properties of instance and calls dump method. - * @returns {Object} - object which represents current state of instance - */ - reset: function () { - this.value(null); - - return this.dump(); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/filter/range.js b/app/code/Magento/Ui/view/base/web/js/listing/filter/range.js deleted file mode 100644 index 69ac544fdb229f0581c28a51ba9bd9f77b9c9c67..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/filter/range.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - './abstract', - 'underscore' -], function (AbstractControl, _) { - 'use strict'; - - return AbstractControl.extend({ - - /** - * Invokes initialize method of parent class and initializes observable properties of instance. - * @param {Object} data - Item of "fields" array from grid configuration - * @param {Object} config - Filter configuration - */ - initialize: function (data, config) { - this.constructor.__super__.initialize.apply(this, arguments); - - this.observe({ - from: '', - to: '' - }); - }, - - /** - * Creates dump copy of current state. - * @return {Object} dumped value object - */ - getValues: function(){ - var value = {}, - from = this.from(), - to = this.to(); - - if (from) { - value.from = from; - } - - if (to) { - value.to = to; - } - - return value; - }, - - /** - * Returns string value of current state for UI - * @return {String} - */ - display: function(){ - var values = this.getValues(); - - return _.map(values, function(value, name){ - return name + ': ' + value; - }).join(' '); - }, - - /** - * Checkes if current state is empty. - * @return {Boolean} - */ - isEmpty: function(){ - return ( !this.to() && !this.from() ); - }, - - /** - * Returns dump of instance's current state - * @returns {Object} - object which represents current state of instance - */ - dump: function () { - this.output( this.display() ); - - return { - field: this.index, - value: this.getValues() - }; - }, - - /** - * Resets state properties of instance and calls dump method. - * @returns {Object} - object which represents current state of instance - */ - reset: function () { - this.to(''); - this.from(''); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/filter/select.js b/app/code/Magento/Ui/view/base/web/js/listing/filter/select.js deleted file mode 100644 index 128cc59eb53b84530fee7c39591ddceeedbfef79..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/filter/select.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - './abstract', - 'underscore' -], function (AbstractControl, _) { - 'use strict'; - - return AbstractControl.extend({ - - /** - * Invokes initialize method of parent class and initializes properties of instance. - * @param {Object} data - Item of "fields" array from grid configuration - * @param {Object} config - Filter configuration - */ - initialize: function (data) { - this.constructor.__super__.initialize.apply(this, arguments); - - this.caption = 'Select...'; - - this.observe('selected', ''); - - this.options = this.options ? this.formatOptions(this.options) : []; - }, - - /** - * Checkes if current state is empty. - * @return {Boolean} - */ - isEmpty: function(){ - var selected = this.selected(); - - return !(selected && selected.value); - }, - - /** - * Formats options property of instance. - * @param {Object} options - object representing options - * @returns {Array} - Options, converted to array - */ - formatOptions: function (options) { - return _.map(options, function (value, key) { - return { value: key, label: value }; - }); - }, - - /** - * Returns string value of current state for UI - * @return {String} - */ - display: function(){ - var selected = this.selected(); - - return selected && selected.label; - }, - - /** - * Returns dump of instance's current state - * @returns {Object} - object which represents current state of instance - */ - dump: function () { - var selected = this.selected(); - - this.output( this.display() ); - - return { - field: this.index, - value: selected && selected.value - } - }, - - /** - * Resets state properties of instance and calls dump method. - * @returns {Object} - object which represents current state of instance - */ - reset: function () { - this.selected(null); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/grid.js b/app/code/Magento/Ui/view/base/web/js/listing/grid.js deleted file mode 100644 index e074902586342a9b8e7b80700eb565468462fcd2..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/grid.js +++ /dev/null @@ -1,222 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'Magento_Ui/js/lib/component', - 'Magento_Ui/js/lib/ko/scope', - 'Magento_Ui/js/lib/mixins/loader', -], function(_, Component, Scope, Loader) { - 'use strict'; - - var Listing = Scope.extend({ - - /** - * Extends instance with defaults and config, initializes observable properties. - * Updates provider with current state of instance. - * @param {Object} settings - */ - initialize: function(settings) { - _.extend(this, settings); - - this.initFields() - .initObservable() - .initListeners() - .updateItems(); - - this.unlock(); - }, - - /** - * Initializes raw properties - * @return {Object} reference to instance - */ - initFields: function(){ - this.meta = this.provider.meta; - this.fields = this.meta.getVisible(); - this.itemActionKey = this.meta.get('item_action'); - - return this; - }, - - /** - * Initializes observable properties of instance. - * @return {Object} - reference to instance - */ - initObservable: function() { - this.observe({ - rows: [], - isLocked: false, - colspan: this.meta.get('colspan'), - extenders: null, - templateExtenders: [] - }); - - return this; - }, - - /** - * Init instance's subscribtions - * @return {Object} - reference to instance - */ - initListeners: function() { - var provider = this.provider, - meta = provider.meta, - dump = provider.dump; - - _.bindAll(this, 'lock', 'onRefresh', 'updateExtenders', 'updateColspan'); - - provider.on({ - 'beforeRefresh': this.lock, - 'refresh': this.onRefresh - }); - - dump.when('update:extenders', this.updateExtenders); - meta.on('update:colspan', this.updateColspan); - - return this; - }, - - /** - * Is being called when some component pushed it's extender to global storage. - * Preprocesses incoming array of extenders and sets the results into extenders - * and templateExtenders observable arrays - * @param {Array} extenders - */ - updateExtenders: function (extenders) { - var adjusted = extenders.reduce(function (adjusted, extender) { - - adjusted[extender.as] = extender.name; - return adjusted; - - }, {}); - - this.extenders(adjusted); - - this.templateExtenders(extenders.map(this.adjustTemplateExtender, this)); - }, - - /** - * Fetches items from storage and stores it into rows observable array - * @return {Object} - reference to instance - */ - updateItems: function() { - var items = this.provider.data.get('items'); - - this.rows(items.map(this.formatItem, this)); - - return this; - }, - - formatItem: function (item) { - var actions = item.actions, - itemActionKey = this.itemActionKey, - itemAction; - - if (actions) { - itemAction = actions[itemActionKey]; - item.action_url = itemAction.href; - - if (itemAction.hidden) { - delete item.actions[itemActionKey]; - } - - item.actions = _.map(item.actions, function (action) { return action }); - } - - return item; - }, - - applyItemActionFor: function (item) { - return this.redirectTo.bind(this, item.action_url); - }, - - /** - * Returns extender by name of component which set it. - * @param {String} name - * @return {String} - Namespace string by which target component is registered in storage. - */ - getExtender: function(name) { - var extenders = this.extenders(); - - return extenders ? (this.parent_name + ':' + extenders[name]) : null; - }, - - /** - * Returns path to template for arbitrary field - * @param {String} field - * @return {String} - path to template - */ - getCellTemplateFor: function(field) { - return this.getRootTemplatePath() + '/cell/' + field.data_type; - }, - - /** - * Returns object which represents template bindings params - * @return {Object} - template binding params - */ - getTemplate: function() { - return { - name: this.getRootTemplatePath(), - extenders: this.templateExtenders() - }; - }, - - /** - * Generates template path for extender. - * @param {Object} extender - * @return {String} - extender's template path - */ - adjustTemplateExtender: function (extender) { - return this.getRootTemplatePath() + '/extender/' + extender.path; - }, - - /** - * Returns root template path for grid - * @return {String} - root template path - */ - getRootTemplatePath: function() { - return 'ui/listing/grid'; - }, - - /** - * Provider's refresh event's handler. - * Locks grid and updates items. - */ - onRefresh: function() { - this.unlock() - .updateItems(); - }, - - /** - * Updates colspan observable property - * @param {String} colspan - */ - updateColspan: function(colspan){ - this.colspan(colspan); - }, - - /** - * Sets location.href to target url - * @param {String} url - */ - redirectTo: function (url) { - if (url) { - window.location.href = url; - } - }, - - /** - * Indicates if rows observable array is empty - * @return {Boolean} [description] - */ - hasData: function(){ - return this.rows().length; - } - }, Loader); - - return Component({ - constr: Listing - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/massaction.js b/app/code/Magento/Ui/view/base/web/js/listing/massaction.js deleted file mode 100644 index 2c559de58d1dc287e2c11a6309f19af27e29f105..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/massaction.js +++ /dev/null @@ -1,414 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'jquery', - 'underscore', - 'Magento_Ui/js/lib/ko/scope', - 'Magento_Ui/js/lib/component', - 'mage/translate' -], function ($, _, Scope, Component) { - 'use strict'; - - function capitaliseFirstLetter(string) { - return string.charAt(0).toUpperCase() + string.slice(1); - } - - var defaults = { - actions: [], - deleteMsg: $.mage.__("Are you sure you want to delete these records?"), - notSelected: $.mage.__("You haven't selected any items!"), - selects: [ - { value: 'selectAll', label: 'Select all' }, - { value: 'deselectAll', label: 'Deselect all' }, - { value: 'selectPage', label: 'Select all on this page' }, - { value: 'deselectPage', label: 'Deselect all on this page' } - ], - selectableTemplate: 'selectable' - }; - - var MassActions = Scope.extend({ - - /** - * Extends instance with defaults and config, initializes observable properties. - * Updates storage with current state of instance. - * @param {Object} config - */ - initialize: function (config) { - _.extend(this, defaults, config); - - this.initObservable() - .initProperties() - .formatActions() - .attachTemplateExtender() - .initListeners() - .countPages(); - }, - - /** - * Initializes observable properties of instance. - * @returns {MassActions} Chainable. - */ - initObservable: function () { - this.observe({ - selected: this.selected || [], - excluded: [], - allSelected: this.allSelected || false, - actionsVisible: false, - menuVisible: false, - hasMultiplePages: '' - }); - - this.selected.subscribe(this.onSelectionsChange.bind(this)); - - return this; - }, - - /** - * Initializes instance properties - * @returns {MassActions} Chainable. - */ - initProperties: function () { - var provider = this.provider.meta; - - this.indexField = provider.get('index_field'); - - return this; - }, - - /** - * Convertes incoming optins to compatible format - * @returns {MassActions} Chainable. - */ - formatActions: function(){ - var actions = this.actions; - - if(!Array.isArray(actions)){ - - this.actions = _.map(actions, function(action, name){ - action.value = name; - - return action; - }); - } - - return this; - }, - - /** - * Attaches it's template to provider.dump's extenders - * @returns {MassActions} Chainable. - */ - attachTemplateExtender: function () { - var provider = this.provider, - dump = provider.dump, - meta = provider.meta, - colspan = meta.get('colspan'), - extenders = dump.get('extenders'); - - if(!this.selectableTemplate) { - return this; - } - - extenders.push({ - path: this.selectableTemplate, - name: this.name, - as: 'massaction' - }); - - dump.resolve('update:extenders', extenders); - meta.set('colspan', colspan + 1); - - return this; - }, - - /** - * Init instance's subscribtions - * @returns {MassActions} Chainable. - */ - initListeners: function(){ - this.provider.on('refresh', this.onRefresh.bind(this)); - - return this; - }, - - /** - * Prepares params object, which represents the current state of instance. - * @returns {Object} - params object - */ - buildParams: function () { - if (this.allSelected()) { - - return { - all_selected: true, - excluded: this.excluded() - }; - } - - return { - selected: this.selected() - }; - }, - - /** - * Toggles observable property based on area argument. - * @param {String} area - Name of the area to be toggled. - */ - toggle: function(area){ - var visible = this[area]; - - visible(!visible()); - }, - - /** - * Sets actionsVisible to false - */ - hideActions: function () { - this.actionsVisible(false); - }, - - /** - * Sets menuVisible to false - */ - hideMenu: function () { - this.menuVisible(false); - }, - - /** - * Updates storage's params by the current state of instance - * and hides dropdowns. - * @param {String} action - */ - setAction: function (action) { - return function(){ - this.submit(action) - .hideActions(); - }.bind(this); - }, - - /** - * Sends actions's data to server. - * @param {Object} action - An action object. - * @returns {MassActions} Chainable. - */ - submit: function(action) { - var client = this.provider.client, - value = action.value, - confirmed = true; - - if (!this.count) { - confirmed = false; - - alert(this.notSelected); - } else if (value === 'delete') { - confirmed = confirm(this.deleteMsg); - } - - if (confirmed) { - client.submit({ - method: 'post', - action: action.url, - data: { - massaction: this.buildParams() - } - }); - } - - return this; - }, - - /** - * Retrieve all id's from available records. - * @param {Boolean} [exclude] - Whether to exclude not selected ids' from result. - * @returns {Array} An array of ids'. - */ - getIds: function(exclude){ - var items = this.provider.data.get('items'), - ids = _.pluck(items, this.indexField); - - return exclude ? - _.difference(ids, this.excluded()) : - ids; - }, - - /** - * Sets isAllSelected observable to true and selects all items on current page. - */ - selectAll: function () { - this.allSelected(true); - - this.clearExcluded() - .selectPage(); - }, - - /** - * Sets isAllSelected observable to false and deselects all items on current page. - */ - deselectAll: function () { - this.allSelected(false); - this.deselectPage(); - }, - - /** - * Selects all items on current page, adding their ids to selected observable array - */ - selectPage: function () { - this.selected(this.getIds()); - }, - - /** - * Deselects all items on current page, emptying selected observable array - */ - deselectPage: function () { - this.selected.removeAll(); - }, - - updateExcluded: function(selected) { - var excluded = this.excluded(), - fromPage = _.difference(this.getIds(), selected); - - excluded = _.union(excluded, fromPage); - - excluded = _.difference(excluded, selected); - - this.excluded(excluded); - - return this; - }, - - /** - * Clears the array of not selected records. - * @returns {MassActions} Chainable. - */ - clearExcluded: function(){ - this.excluded.removeAll(); - - return this; - }, - - /** - * Returns handler for row click - * @param {String} url - * @return {Function} click handler - */ - redirectTo: function (url) { - - /** - * Sets location.href to target url - */ - return function () { - window.location.href = url; - } - }, - - /** - * Gets current pages count and assignes it's being more than one to - * hasMultiplePages observable. - * @returns {MassActions} Chainable. - */ - countPages: function() { - var provider = this.provider.data; - - this.pages = provider.get('pages'); - - this.hasMultiplePages(this.pages > 1); - - return this; - }, - - /** - * Counts number of 'selected' items. - * @returns {MassActions} Chainable. - */ - countSelect: function() { - var provider = this.provider, - total = provider.data.get('totalCount'), - excluded = this.excluded().length, - count = this.selected().length; - - if (this.allSelected()) { - count = total - excluded; - } - - provider.meta.set('selected', count); - - this.count = count; - - return this; - }, - - /** - * If isAllSelected is true, deselects all, else selects all - */ - toggleSelectAll: function () { - var isAllSelected = this.allSelected(); - - isAllSelected ? this.deselectAll() : this.selectAll(); - }, - - /** - * Looks up for corresponding to passed action checker method, - * and returnes it's result. If method not found, returnes true; - * @param {String} action - e.g. selectAll, deselectAll - * @returns {Boolean} should action be visible - */ - shouldBeVisible: function (action) { - var checker = this['should' + capitaliseFirstLetter(action) + 'BeVisible']; - - return checker ? checker.call(this) : true; - }, - - /** - * Checkes if selectAll action supposed to be visible - * @returns {Boolean} - */ - shouldSelectAllBeVisible: function () { - return !this.allSelected() && this.hasMultiplePages(); - }, - - /** - * Checkes if deselectAll action supposed to be visible - * @returns {Boolean} - */ - shouldDeselectAllBeVisible: function () { - return this.allSelected() && this.hasMultiplePages(); - }, - - onToggle: function(area){ - return this.toggle.bind(this, area); - }, - - /** - * Creates handler for applying action (e.g. selectAll) - * @param {String} action - * @returns {Function} - click handler - */ - onApplySelect: function (action) { - return function(){ - this.menuVisible(false); - this[action](); - }.bind(this); - }, - - /** - * Updates state according to changes of provider. - */ - onRefresh: function () { - if( this.allSelected() ){ - this.selected(this.getIds(true)); - } - - this.countPages(); - }, - - onSelectionsChange: function(selected){ - this.updateExcluded(selected) - .countSelect(); - } - }); - - return Component({ - constr: MassActions - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/paging.js b/app/code/Magento/Ui/view/base/web/js/listing/paging.js deleted file mode 100644 index c32df63ed9b108c39bad296081b2e6abade4b1a2..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/paging.js +++ /dev/null @@ -1,191 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - '../lib/ko/scope', - '../lib/component' -], function(_, Scope, Component) { - 'use strict'; - - var defaults = { - sizes: [5, 10, 20, 30, 50, 100, 200], - params: { - dir: 'paging', - items: ['pageSize', 'current'] - } - }; - - var Paging = Scope.extend({ - - /** - * Extends instance with defaults and config, initializes observable properties. - * Updates storage with current state of instance. - * @param {Object} config - */ - initialize: function(config) { - _.extend(this, defaults, config); - - this.initObservable(config) - .initProvider() - .pushParams(); - }, - - /** - * Initializes observable properties of instance. - * @return {Object} - reference to instance - */ - initObservable: function(config) { - var data = this.provider.data.get(); - - this.observe({ - 'pages': data.pages || 1, - 'totalCount': data.totalCount, - 'current': this.current, - 'pageSize': this.pageSize, - 'selected': 0 - }); - - return this; - }, - - /** - * Subscribes on provider's events - * @returns {Paging} Chainable. - */ - initProvider: function(){ - var provider = this.provider, - params = provider.params, - meta = provider.meta; - - _.bindAll(this, 'drop', 'onRefresh', 'pullParams', 'updateSelected'); - - provider.on('refresh', this.onRefresh); - - meta.on('update:selected', this.updateSelected); - - params.on({ - 'update:filter': this.drop, - 'update:sorting': this.drop, - 'update:paging': this.pullParams - }); - - return this; - }, - - /** - * Increments current observable prop by val and call reload method - * @param {String} val - */ - go: function(val) { - var current = this.current; - - current(current() + val); - - this.reload(); - }, - - /** - * Calls go method with 1 as agrument - */ - next: function() { - this.go(1); - }, - - /** - * Calls go method with -1 as agrument - */ - prev: function() { - this.go(-1); - }, - - /** - * Compares current and pages observables and returns boolean result - * @return {Boolean} is current equal to pages property - */ - isLast: function() { - return this.current() === this.pages(); - }, - - /** - * Compares current observable to 1 - * @return {Boolean} is current page first - */ - isFirst: function() { - return this.current() === 1; - }, - - /** - * Returns closest existing page number to page argument - * @param {Number} page - * @return {Number} closest existing page number - */ - getInRange: function(page) { - return Math.min(Math.max(1, page), this.pages()); - }, - - /** - * Sets current observable to 1 and calls pushParams method - */ - drop: function() { - this.current(1); - - this.pushParams(); - }, - - /** - * Updates number of selected items. - * @param {Number} count - New number of selected items. - */ - updateSelected: function(count){ - this.selected(count); - }, - - /** - * Is being called on provider's refresh event. - * Updates totalCount and pages observables - */ - onRefresh: function() { - var data = this.provider.data.get(); - - this.totalCount(data.totalCount); - this.pages(data.pages || 1); - }, - - /** - * Is being triggered on user interaction with page size select. - * Resets current page to first if needed. - */ - onSizeChange: function() { - var size = this.pageSize(); - - if (size * this.current() > this.totalCount()) { - this.current(1); - } - - this.reload(); - }, - - /** - * Validates page change according to user's input. - * Sets current observable to result of validation. - * Calls reload method then. - */ - onPageChange: function() { - var current, - valid; - - current = +this.current(); - valid = !isNaN(current) ? this.getInRange(current) : 1; - - this.current(valid); - - this.reload(); - } - }); - - return Component({ - constr: Paging - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/listing/sorting.js b/app/code/Magento/Ui/view/base/web/js/listing/sorting.js deleted file mode 100644 index 31b9812713c32d285a76f33d1672d27bfbf0eaf3..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/js/listing/sorting.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'Magento_Ui/js/lib/ko/scope', - 'Magento_Ui/js/lib/component' -], function(_, Scope, Component) { - 'use strict'; - - var defaults = { - dirs: { - asc: 'sort-arrow-asc', - desc: 'sort-arrow-desc' - }, - params: { - dir: 'sorting', - items: ['field', 'direction'] - }, - initialDir: 'asc', - noSort: 'not-sort', - templateExtender: 'sortable' - }; - - var Sorting = Scope.extend({ - - /** - * Extends instance with defaults and config, initializes observable properties. - * Updates storage with current state of instance. - * @param {Object} config - */ - initialize: function(config) { - _.extend(this, defaults, config); - - this.initObservable() - .attachTemplateExtender() - .pushParams(); - }, - - /** - * Initializes observable properties of instance. - * @returns {Sorting} Chainable. - */ - initObservable: function(){ - this.observe('field direction'); - - return this; - }, - - /** - * Attaches it's template to provider.dump's extenders - * @returns {Sorting} Chainable. - */ - attachTemplateExtender: function () { - var dump = this.provider.dump, - extenders = dump.get('extenders'); - - extenders.push({ - path: this.templateExtender, - name: this.name, - as: 'sorting' - }); - - dump.resolve('update:extenders', extenders); - - return this; - }, - - /** - * Generates css class for indicating sorting state for field. - * @param {String} id - identifier of field to be sorted - * @returns {String} - css class. - */ - setClass: function(id) { - return this.isSorted(id) ? - this.dirs[this.direction()] : - this.noSort; - }, - - /** - * Toggles observable dir property betweeen 'asc' and 'desc' values. - */ - toggleDirection: function() { - var dir = this.direction; - - dir(dir() === 'asc' ? 'desc' : 'asc'); - }, - - /** - * Sets currently sorted field and initial sorting type for it. - * @param {String} id - identifier of field to be sorted - */ - setSort: function(id) { - this.field(id); - this.direction(this.initialDir); - }, - - /** - * Sorts by field and reloads storage. - * @param {(String|Number)} id - Identifier of field to be sorted. - */ - sortBy: function(id) { - this.isSorted(id) ? - this.toggleDirection() : - this.setSort(id); - - this.reload(); - }, - - /** - * Checks if the field is currently sorted. - * @param {String} id - identifier of field to be sorted - * @returns {Boolean} true, if target field is sorted already, false otherwise - */ - isSorted: function(id) { - return id === this.field(); - }, - - /** - * Returns function to handle user's click (workaround for knockout.js). - * @param {Object} field - * @returns {Function} - click handler - */ - onClick: function(field) { - return this.sortBy.bind(this, field.index); - } - }); - - return Component({ - constr: Sorting - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/area.html b/app/code/Magento/Ui/view/base/web/templates/area.html index 867908c0f8eeda3b65128cfb31653bda3bea0aee..eee2d4a8c630dcf93ab48c1911ed1b0b7237de1b 100644 --- a/app/code/Magento/Ui/view/base/web/templates/area.html +++ b/app/code/Magento/Ui/view/base/web/templates/area.html @@ -4,7 +4,6 @@ * See COPYING.txt for license details. */ --> - <!-- ko if: wasActivated --> <div data-bind="visible: active"> <!-- ko foreach: elems --> diff --git a/app/code/Magento/Ui/view/base/web/templates/content/content.html b/app/code/Magento/Ui/view/base/web/templates/content/content.html index c3d84628b7721cfd63b07a65ab4e66e623b122c9..ad90f63cd4282170e5322957e7bda90ac42f2291 100644 --- a/app/code/Magento/Ui/view/base/web/templates/content/content.html +++ b/app/code/Magento/Ui/view/base/web/templates/content/content.html @@ -7,7 +7,7 @@ <div data-bind="html: content, attr: {class: element.cssclass ? element.cssclass : 'admin__scope-old'}"></div> <!--ko if: showSpinner --> -<div data-role="spinner" class="grid-loading-mask" data-bind="visible: loading"> - <div class="spinner"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div> +<div data-role="spinner" class="admin__data-grid-loading-mask" data-bind="visible: loading"> + <span class="grid-loader"></span> </div> <!-- /ko --> diff --git a/app/code/Magento/Ui/view/base/web/templates/filter.html b/app/code/Magento/Ui/view/base/web/templates/filter.html deleted file mode 100644 index 0f95ab6ae6e9cf87ce69cc39a9d99c3ed9d75f1b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/filter.html +++ /dev/null @@ -1,42 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<div class="filters"> - <button class="action filters-toggle" data-bind="click: toggle, css: { active: isVisible }"> - <span data-bind="text: $t('Filter')"></span> - </button> - <div class="form filters-form" data-bind="visible: isVisible" data-part="filter-form"> - <fieldset class="filters-fieldset fieldset"> - <legend class="legend filters-legend"> - <span data-bind="text: $t('Advanced filter')"></span> - </legend><br /> - <!-- ko foreach: { data: filters, as: 'item' } --> - <!-- ko template: item.getTemplate() --><!-- /ko --> - <!-- /ko --> - </fieldset> - <div class="actions filters-actions"> - <button class="action secondary action-reset" data-bind="click: reset" type="button"><span data-bind="text: $t('Reset')"></span></button> - <button class="action primary action-apply" data-bind="click: apply" type="button"><span data-bind="text: $t('Apply')"></span></button> - <button class="action secondary action-close" data-bind="click: close" type="button"><span data-bind="text: $t('Close')"></span></button> - </div> - </div> - <div class="filters-current" data-bind="css: {active: active().length}"> - <ul class="filters-items items"> - <!-- ko foreach: { data: active, as: 'filter' } --> - - <li class="filters-item item"> - <strong class="item-label" data-bind="text: $t(filter.label)"></strong> - <span class="item-value" data-bind="text: $t(filter.output)"></span> - <button data-bind="click: $parent.onClear(filter)" type="button" class="action action-remove"><span data-bind="text: $t('Remove')"></span></button> - </li> - - <!-- /ko --> - </ul> - <button data-bind="click: reset" class="action action-clear"> - <span data-bind="text: $t('Clear all')"></span> - </button> - </div> -</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/filter/filter_date.html b/app/code/Magento/Ui/view/base/web/templates/filter/filter_date.html deleted file mode 100644 index 644aad7f8301f550f871700dbe25381e5b608b11..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/filter/filter_date.html +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<fieldset class="field field-range field-date"> - <legend class="label"> - <span data-bind="text: label"></span> - </legend><br /> - <div class="control"> - <div class="fields group group-2"> - <div class="field field-range-from"> - <label class="label"><span data-bind="text: $t('From')"></span></label> - <div class="control"> - <input type="text" class="input-text no-changes" data-bind="datepicker: { storage: from, options: config }, attr: {placeholder: $t('From')}"> - </div> - </div> - <div class="field field-range-to"> - <label class="label"><span data-bind="text: $t('To')"></span></label> - <div class="control"> - <input type="text" class="input-text no-changes" data-bind="datepicker: { storage: to, options: config }, attr: {placeholder: $t('To')}"> - </div> - </div> - </div> - </div> -</fieldset> diff --git a/app/code/Magento/Ui/view/base/web/templates/filter/filter_input.html b/app/code/Magento/Ui/view/base/web/templates/filter/filter_input.html deleted file mode 100644 index 0550a3907fca34af7173d0b75d40e9edd0b64327..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/filter/filter_input.html +++ /dev/null @@ -1,14 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<div class="field"> - <label class="label" data-bind="attr: {for: index}"> - <span data-bind="text: label"></span> - </label> - <div class="control"> - <input data-bind="value: value, attr: {id: index}" class="input-text" type="text"> - </div> -</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/filter/filter_range.html b/app/code/Magento/Ui/view/base/web/templates/filter/filter_range.html deleted file mode 100644 index f34b97cb89bb854436ba71d072a0b520b8f88873..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/filter/filter_range.html +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<fieldset class="field field-range"> - <legend class="label"> - <span data-bind="text: label"></span> - </legend><br /> - <div class="control"> - <div class="fields group group-2"> - <div class="field field-range-from"> - <label class="label"><span data-bind="text: $t('From')"></span></label> - <div class="control hide-picker"> - <input type="text" class="input-text no-changes" data-bind="value: from, attr: {placeholder: $t('From')}"> - </div> - </div> - <div class="field field-range-to"> - <label class="label"><span data-bind="text: $t('To')"></span></label> - <div class="control hide-picker"> - <input type="text" class="input-text no-changes" data-bind="value: to, attr: {placeholder: $t('To')}"> - </div> - </div> - </div> - </div> -</fieldset> diff --git a/app/code/Magento/Ui/view/base/web/templates/filter/filter_select.html b/app/code/Magento/Ui/view/base/web/templates/filter/filter_select.html deleted file mode 100644 index 22be5c2d159a35a11acc731c8d6fc61c641c4216..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/filter/filter_select.html +++ /dev/null @@ -1,14 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<div class="field"> - <label class="label" data-bind="attr: {for: index}"> - <span data-bind="text: label"></span> - </label> - <div class="control"> - <select data-bind="attr: {id: index}, options: options, value: selected, optionsText: 'label', optionsCaption: caption" class="select"></select> - </div> -</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/collection.html b/app/code/Magento/Ui/view/base/web/templates/form/components/collection.html index 5fd7ccc4bfed8874636abd5fa9c154c65ffc6422..05234c4afad7ace8a0e7261599b03eddf7c26260 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/collection.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/collection.html @@ -10,12 +10,12 @@ <!-- ko foreach: { data: element.elems, as: 'element' } --> <li class="address-list-item" data-bind="css: { 'ui-state-active': element.active }, click: activate"> <div class="address-list-item-actions"> - <button class="action-delete" type="button" data-bind="click: $parent.removeChild(element)"> + <button class="action-delete" type="button" data-bind="click: $parent.removeChild.bind($parent, element)"> <span data-bind="text: $parent.removeLabel"></span> </button> </div> <!-- ko template: previewTpl --><!-- /ko --> - <div data-bind="foreach: { data: element.head, as: 'element' }, stopPropagation: true"> + <div data-bind="foreach: { data: element.getRegion('head'), as: 'element' }, stopPropagation: true"> <!-- ko template: element.getTemplate() --><!-- /ko --> </div> </li> @@ -35,7 +35,7 @@ <span data-bind="text: $parent.label"></span> </legend> <br> - <!-- ko foreach: { data: element.body, as: 'element' } --> + <!-- ko foreach: { data: element.getRegion('body'), as: 'element' } --> <!-- ko template: element.getTemplate() --><!-- /ko --> <!-- /ko --> </fieldset> diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/collection/item.html b/app/code/Magento/Ui/view/base/web/templates/form/components/collection/item.html deleted file mode 100644 index f274c3fe90f9396d739d94618104f4c4a0f7755d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/collection/item.html +++ /dev/null @@ -1,10 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<!-- ko foreach: { data: elems, as: 'element' } --> - <!-- ko template: element.getTemplate() --><!-- /ko --> -<!-- /ko --> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/collection/preview.html b/app/code/Magento/Ui/view/base/web/templates/form/components/collection/preview.html index eed7c6acc697fbc9ce46ac7e1b9392a2064ada52..96ac887a7fb4aa9d40b21aea255d860c71048313 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/collection/preview.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/collection/preview.html @@ -9,7 +9,7 @@ data: formatPreviews([ "prefix firstname middlename lastname suffix", "company", - "street", + "street_container", { items: "city region_id postcode", separator: ", " diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox.html b/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox.html index 1f712a604aba029f64399a5063e0faf8e964a7a3..01dca8a5b9318157f562333f27546e07f3d0e081 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox.html @@ -8,12 +8,7 @@ <input type="checkbox" class="admin__control-checkbox" data-bind="checked: value, attr: { id: uid, disabled: disabled, name: inputName }, hasFocus: focused"> <label class="admin__field-label" data-bind="checked: value, attr: { for: uid }"> - <!-- ko if: $parent.isSingle() --> - <span data-bind="text: description"></span> - <!-- /ko --> - <!-- ko if: !$parent.isSingle() --> - <span data-bind="text: description || label"></span> - <!-- /ko --> + <span data-bind="text: description || label"></span> </label> <!-- ko if: notice --> diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/textarea.html b/app/code/Magento/Ui/view/base/web/templates/form/element/textarea.html index 8aa979d0658994b3bb64d9f397e991f1bb4891bd..fa1f88ddc1fc2fdee3578b0799b5519c5ab2d8af 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/textarea.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/textarea.html @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ --> + <textarea class="admin__control-textarea" data-bind=" value: value, hasFocus: focused, diff --git a/app/code/Magento/Ui/view/base/web/templates/group/field.html b/app/code/Magento/Ui/view/base/web/templates/form/field.html similarity index 69% rename from app/code/Magento/Ui/view/base/web/templates/group/field.html rename to app/code/Magento/Ui/view/base/web/templates/form/field.html index e01470fa2aed8f7e15547bcc6c2e20f909bb9f69..8ba9dc8d3474a539de251007e8f994bb2e4e163f 100644 --- a/app/code/Magento/Ui/view/base/web/templates/group/field.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/field.html @@ -4,22 +4,22 @@ * See COPYING.txt for license details. */ --> -<div class="admin__field" data-bind="css: {'_required': element.required, '_disabled': element.disabled, '_error': element.error}"> +<div class="admin__field" data-bind="visible: visible, css: {'_required': element.required, '_disabled': element.disabled, '_error': element.error}"> <!-- ko if: element.label --> - <label class="admin__field-label" data-bind="attr: { for: element.uid }, css: {'_dublicated': element.label === $parent.label}"> + <label class="admin__field-label" data-bind="attr: { for: element.uid }"> <span data-bind="text: element.label"></span> </label> <!-- /ko --> <div class="admin__field-control"> <!-- ko ifnot: element.hasAddons() --> - <!-- ko template: element.getTemplate() --><!-- /ko --> + <!-- ko template: element.elementTmpl --><!-- /ko --> <!-- /ko --> <!-- ko if: element.hasAddons() --> <div class="admin__control-addon"> - <!-- ko template: element.getTemplate() --><!-- /ko --> + <!-- ko template: element.elementTmpl --><!-- /ko --> <!-- ko if: element.addbefore --> <label class="admin__addon-prefix" data-bind="attr: { for: element.uid }"><span data-bind="text: element.addbefore"></span></label> @@ -39,10 +39,9 @@ <div class="admin__field-note" data-bind="attr: { id: element.noticeId }"><span data-bind="text: element.notice"></span></div> <!-- /ko --> - <!-- ko if: $parent.isSingle() --> - <!-- ko if: element.error() && !element.hidden() --> - <label class="admin__field-error" data-bind="attr: { for: element.uid }, text: element.error"></label> - <!-- /ko --> + <!-- ko if: element.error() --> + <label class="admin__field-error" data-bind="attr: { for: element.uid }, text: element.error"></label> <!-- /ko --> </div> </div> +<!-- /ko --> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/fieldset/fieldset.html b/app/code/Magento/Ui/view/base/web/templates/form/fieldset.html similarity index 89% rename from app/code/Magento/Ui/view/base/web/templates/fieldset/fieldset.html rename to app/code/Magento/Ui/view/base/web/templates/form/fieldset.html index 7a5dc7460dc556de2f622e73d39f25f079d80126..159511ae9c30c14519ec7fc19a5978a7602b5402 100644 --- a/app/code/Magento/Ui/view/base/web/templates/fieldset/fieldset.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/fieldset.html @@ -4,9 +4,9 @@ * See COPYING.txt for license details. */ --> -<!-- ko if: elems --> + <div class="admin__fieldset-wrapper" data-bind="css: {'collapsable-wrapper': collapsible, 'opened': opened}"> - <div class="admin__fieldset-wrapper-title" tabindex="3" data-bind="click: onClick, keyboard: { 13: toggle }"> + <div class="admin__fieldset-wrapper-title" tabindex="3" data-bind="click: toggleOpened, keyboard: { 13: toggleOpened }"> <strong class="title"> <span data-bind="text: label"></span> </strong> @@ -19,4 +19,3 @@ </fieldset> </div> </div> -<!-- /ko --> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/actions.html b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html new file mode 100644 index 0000000000000000000000000000000000000000..685936aa8430382b59ff1b065c74e244aadcd24a --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html @@ -0,0 +1,29 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="col-xs-2"> + <div + class="action-select-wrap" + data-bind="css: {'_active': opened}, + click: toggleOpened, + outerClick: close"> + <button + class="action-select" + data-bind="title: $t('Select Items')"> + <span data-bind="text: $t('Actions')"></span> + </button> + <ul + class="action-menu" + data-bind="css: {'_active': opened}, + foreach: {data: actions, as: 'action'}"> + <li data-bind="click: $parent.applyAction.bind($parent, action)"> + <span + class="action-menu-item" + data-bind="text: label"></span> + </li> + </ul> + </div> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/actions.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/actions.html new file mode 100644 index 0000000000000000000000000000000000000000..1ef5fc1177e73194f9bf29a7d27554c85de47a6f --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/actions.html @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<td class="data-grid-actions-cell"> + <!-- ko if: getDisplayed(row[field.index]).length > 1 --> + <div class="action-select-wrap _active"> + <button class="action-select"> + <span data-bind="text: $t('Select')"></span> + </button> + <ul class="action-menu _active"> + <li> + <a + class="action-menu-item" + data-bind="attr: {href: displayed[0].href}, + text: displayed[0].label"></a> + </li> + </ul> + </div> + <!-- /ko --> + <!-- ko ifnot: getDisplayed(row[field.index]).length > 1 --> + <a + class="action-menu-item" + data-bind="attr: {href: displayed[0].href}, + text: displayed[0].label"></a> + <!-- /ko --> +</td> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/multiselect.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/multiselect.html new file mode 100644 index 0000000000000000000000000000000000000000..81e6b2c5bc3706a042daf1f6e2b3725e84b681c4 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/multiselect.html @@ -0,0 +1,18 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<td class="data-grid-checkbox-cell"> + <label class="data-grid-checkbox-cell-inner"> + <input + class="admin__control-checkbox" + type="checkbox" + data-bind="checked: selected, + value: row[indexField], + attr: {id: 'check' + row[indexField]}"> + <label data-bind="attr: {for: 'check' + row[indexField]}"></label> + </label> +</td> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html new file mode 100644 index 0000000000000000000000000000000000000000..aff66b7cc2c68a98579a076540dfe22a674c6654 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html @@ -0,0 +1,16 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<!-- ko if: isClickable(row) --> +<td + data-bind="click: redirect.bind($data, getClickUrl(row)), + html: getLabel(row[field.index])" + data-action="grid-row-edit"></td> +<!-- /ko --> +<!-- ko ifnot: isClickable(row) --> +<td data-bind="html: getLabel(row[field.index])"></td> +<!-- /ko --> diff --git a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/store.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/actions.html similarity index 52% rename from app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/store.html rename to app/code/Magento/Ui/view/base/web/templates/grid/columns/actions.html index c6e156ce8e99032c45c93a7c6992787a08785547..ff0980dbe37979d4568ec2b5b8d7d41e6772fb6d 100644 --- a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/store.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/actions.html @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ --> -<td data-part="body.row.cell"> - <span data-bind="html: row[field.index]"></span> -</td> \ No newline at end of file + +<th class="data-grid-th data-grid-actions-cell"> + <span data-bind="text: label"></span> +</th> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/columns/multiselect.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/multiselect.html new file mode 100644 index 0000000000000000000000000000000000000000..8553c127d60cbe35ea144d206a96c5294e389cc0 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/multiselect.html @@ -0,0 +1,41 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<th class="data-grid-multiselect-cell"> + <div + class="action-multiselect-wrap" + data-bind="css: { '_active': menuVisible, '_disabled': !totalRecords()}, + outerClick: hideMenu"> + <input + id="mass-select-checkbox" + class="admin__control-checkbox" + type="checkbox" + data-bind="checked: allSelected, + event: { change: toggleSelectAll }, + css: { '_indeterminate': indetermine }, + enable: totalRecords"> + <label for="mass-select-checkbox"></label> + <button + class="action-multiselect-toggle" + data-toggle="dropdown" + data-bind="css: { '_active': menuVisible }, + click: toggleMenu, + enable: totalRecords"> + <span data-bind="text: $t('Options')"></span> + </button> + <ul + class="action-menu" + data-bind="click: hideMenu"> + <!-- ko foreach: actions --> + <li data-bind="click: $parent[value].bind($parent), + visible: $parent.isActionRelevant(value)"> + <span class="action-menu-item" data-bind="text: label"></span> + </li> + <!-- /ko --> + </ul> + </div> +</th> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/columns/text.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/text.html new file mode 100644 index 0000000000000000000000000000000000000000..9f708c21f093a5f8c4e9a6c53eddd3ee2adb04a5 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/text.html @@ -0,0 +1,20 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<!-- ko if: sortable --> + <th + class="data-grid-th _sortable" + data-bind="css: sortClass, click: sort"> + <span data-bind="text: label"></span> + </th> +<!-- /ko --> + +<!-- ko ifnot: sortable --> + <th class="data-grid-th"> + <span data-bind="text: label"></span> + </th> +<!-- /ko --> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/columns.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/columns.html new file mode 100644 index 0000000000000000000000000000000000000000..fafa87cfc8b505d1005959c03d513081ac382a7e --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/columns.html @@ -0,0 +1,45 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div data-bind="css: {_active: opened}, outerClick: close" class="admin__action-dropdown-wrap admin__data-grid-action-columns"> + <button + class="admin__action-dropdown" + type="button" + data-bind="click: toggleOpened" + data-toggle="dropdown" + aria-haspopup="true"> + <span class="admin__action-dropdown-text" data-bind="text: $t('Columns')"></span> + </button> + <div data-bind="css: {_overflow: hasOverflow()}" class="admin__action-dropdown-menu admin__data-grid-action-columns-menu"> + <div class="admin__action-dropdown-menu-header"> + <span data-bind="text: getHeaderMessage($t('<%- visible %> out of <%- total %> visible'))"></span> + </div> + <div class="admin__action-dropdown-menu-content"> + <!-- ko foreach: elems --> + <div class="admin__field-option"> + <input data-bind="attr: {id: 'grid-controls-columns-' + index}, disable: $parent.isDisabled($data), checked: visible" + class="admin__control-checkbox" type="checkbox"/> + <label data-bind="text: label, attr: {for: 'grid-controls-columns-' + index}" class="admin__field-label"></label> + </div> + <!-- /ko --> + </div> + <div class="admin__action-dropdown-menu-footer"> + <div class="admin__action-dropdown-footer-secondary-actions"> + <button data-bind="click: reset" class="action-tertiary" type="button"> + <span data-bind="text: $t('Reset')"></span> + </button> + </div> + <div class="admin__action-dropdown-footer-main-actions"> + <button data-bind="click: cancel" class="action-tertiary" type="button"> + <span data-bind="text: $t('Cancel')"></span> + </button> + <button data-bind="click: apply" class="action-secondary" type="button"> + <span data-bind="text: $t('Apply')"></span> + </button> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/view.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/view.html new file mode 100644 index 0000000000000000000000000000000000000000..fc4e1bd8656b7687d787b082da6b1fe0f3d7e000 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/view.html @@ -0,0 +1,60 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div + class="admin__action-dropdown-wrap admin__data-grid-action-bookmarks _hide" + data-bind="css: {_active: opened, _disabled: !collapsible}, outerClick: close"> + <button + class="admin__action-dropdown" + type="button" + data-bind="click: toggleOpened" + data-toggle="dropdown" + aria-haspopup="true"> + <span class="admin__action-dropdown-text">Default View</span> + </button> + <ul class="admin__action-dropdown-menu"> + <!-- ko foreach: {data: sampleData, as: 'view'} --> + <li + data-bind="css: {_edit: false}"> + <div class="action-dropdown-menu-item-edit"> + <input + class="admin__control-text" + data-bind="value: view.label" + type="text"> + <button + class="action-submit" + type="button"> + <span>Submit</span> + </button> + <div class="action-dropdown-menu-item-actions"> + <button + class="action-delete" + type="button"> + <span>Delete</span> + </button> + </div> + </div> + <div class="action-dropdown-menu-item"> + <a + class="action-dropdown-menu-link" + href="" + data-bind="text: view.label"></a> + <div class="action-dropdown-menu-item-actions"> + <button + class="action-edit" + type="button"> + <span>Edit</span> + </button> + </div> + </div> + </li> + <!-- /ko --> + <li class="action-dropdown-menu-item-last"> + <a href="">Save Current View</a> + </li> + </ul> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/date.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/date.html new file mode 100644 index 0000000000000000000000000000000000000000..9fbd4a2b336d69242c5e00d56fa9ca247ebee274 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/date.html @@ -0,0 +1,27 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="admin__form-field"> + <label + class="admin__form-field-label" + data-bind="attr: {for: uid}"> + <span data-bind="text: label"></span> + </label> + <div class="admin__form-field-control"> + <input + class="admin__control-text" + type="text" + data-bind="hasFocus: focused, + datepicker: { storage: value, options: options }, + attr: { + value: value, + name: inputName, + 'aria-describedby': noticeId, + disabled: disabled + }" /> + </div> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/group.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/group.html new file mode 100644 index 0000000000000000000000000000000000000000..a0374eb43cbacd05d18bc163641bd9198edc4b57 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/group.html @@ -0,0 +1,15 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<fieldset class="admin__form-field"> + <legend class="admin__form-field-legend"> + <span data-bind="text: label"></span> + </legend> + <!-- ko foreach: elems --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> +</fieldset> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/input.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/input.html new file mode 100644 index 0000000000000000000000000000000000000000..8e93919ff881319024fc23dea95dd2e17fc37635 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/input.html @@ -0,0 +1,27 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="admin__form-field"> + <label + class="admin__form-field-label" + data-bind="attr: {for: uid}"> + <span data-bind="text: label"></span> + </label> + <div class="admin__form-field-control"> + <input + class="admin__control-text" + type="text" + data-bind="value: value, + hasFocus: focused, + attr: { + name: inputName, + 'aria-describedby': noticeId, + id: uid, + disabled: disabled + }" /> + </div> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/select.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/select.html new file mode 100644 index 0000000000000000000000000000000000000000..abd2502ba19b07f80d55f191ddd6bc587acedc61 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/select.html @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="admin__form-field"> + <label + class="admin__form-field-label" + data-bind="attr: {for: uid}"> + <span data-bind="text: label"></span> + </label> + <div class="admin__field-control"> + <select + class="admin__control-select" + data-bind="attr: { + name: inputName, + id: uid, + disabled: disabled, + 'aria-describedby': noticeId, + placeholder: placeholder + }, + hasFocus: focused, + optgroup: options, + value: value, + optionsCaption: caption, + optionsValue: 'value', + optionsText: 'label'"/> + </div> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html new file mode 100644 index 0000000000000000000000000000000000000000..ddda29706153af351d5faf217d1fc13459005783 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html @@ -0,0 +1,108 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="data-grid-search-control-wrap"> + <input + class="admin__control-text data-grid-search-control" + placeholder="Search by keyword" + type="text"/> + <button + class="action-submit" + type="submit"><span data-bind="text: $t('Search')"></span></button> + <ul class="action-menu _active"> + <li> + <a class="action-menu-item" href>Lorem</a> + </li> + <li> + <a class="action-menu-item" href>Lorem 1</a> + </li> + <li> + <a class="action-menu-item" href>Lorem 2</a> + </li> + </ul> +</div> + +<div class="data-grid-filters-actions-wrap"> + <div class="data-grid-filters-action-wrap"> + <button + class="action-default _active" + data-action="grid-filter-expand" + data-bind="click: toggleOpened, css: { _active: opened }"> + <span data-bind="text: $t('Filters')"></span> + </button> + </div> +</div> + +<div + class="admin__data-grid-filters-current" + data-bind="css: {_show: active().length && !opened()}"> + <div class="admin__current-filters-title-wrap"> + <span + class="admin__current-filters-title" + data-bind="text: $t('Active filters:')"></span> + </div> + <div class="admin__current-filters-list-wrap"> + <ul class="admin__current-filters-list"> + <!-- ko foreach: previews --> + <li> + <span data-bind="text: label + ':'"></span> + <span data-bind="text: preview"></span> + <button + class="action-remove" + data-bind="click: $parent.reset.bind($parent, elem)" + type="button"> + <span data-bind="text: $t('Remove')"></span> + </button> + </li> + <!-- /ko --> + </ul> + </div> +</div> + +<div + class="admin__data-grid-filters-wrap" + data-bind="css: { _show: opened }" + data-part="filter-form"> + + <fieldset class="admin__fieldset admin__data-grid-filters"> + <legend class="admin__filters-legend"> + <span data-bind="text: $t('Advanced filter')"></span> + </legend> + <!-- ko foreach: elems --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </fieldset> + + <div class="admin__data-grid-filters-footer"> + <div class="admin__footer-secondary-actions"> + <button + class="action-tertiary" + type="button" + data-action="grid-filter-reset" + data-bind="click: reset"> + <span data-bind="text: $t('Reset')"></span> + </button> + </div> + <div class="admin__footer-main-actions"> + <button + class="action-tertiary" + type="button" + data-action="grid-filter-cancel" + data-bind="click: close"> + <span data-bind="text: $t('Cancel')"></span> + </button> + <button + class="action-secondary" + type="button" + data-action="grid-filter-apply" + data-bind="click: apply"> + <span data-bind="text: $t('Apply Filters')"></span> + </button> + </div> + </div> + +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/listing.html b/app/code/Magento/Ui/view/base/web/templates/grid/listing.html new file mode 100644 index 0000000000000000000000000000000000000000..544a998a4dbc79e0dc08f0297b8d3821cf0d9fc1 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/listing.html @@ -0,0 +1,38 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<table class="data-grid"> + <thead data-part="head"> + <tr data-part="head.row"> + <!-- ko foreach: elems --> + <!-- ko if: visible --> + <!-- ko template: getHeader() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + </tr> + </thead> + <tbody data-part="body"> + <!-- ko if: hasData() --> + <!-- ko foreach: { data: rows, as: 'row' } --> + <tr data-part="body.row"> + <!-- ko foreach: { data: $parent.elems, as: 'field' } --> + <!-- ko if: visible --> + <!-- ko template: getBody() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + </tr> + <!-- /ko --> + <!-- /ko --> + + <!-- ko ifnot: hasData() --> + <tr class="data-grid-tr-no-data"> + <td data-bind="attr: { colspan: getColspan() }, + text: $t('We couldn\'t find any records.')"></td> + </tr> + <!-- /ko --> + </tbody> +</table> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging.html new file mode 100644 index 0000000000000000000000000000000000000000..9f4f5cc2fdcb5101d7e3969bf9e06ae1be8e0af9 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging.html @@ -0,0 +1,50 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="col-xs-3"> + <div class="admin__control-support-text"> + <span data-bind="text: totalRecords"></span> records found + <!-- ko if: totalSelected --> + (<span data-bind="text: totalSelected"></span> selected) + <!-- /ko --> + </div> +</div> + +<div class="col-xs-7 admin__data-grid-pager-wrap"> + <select + id="perPage" + class="admin__control-select" + data-bind="options: options, + value: pageSize, + optionsValue: 'value', + optionsText: 'label'"></select> + <label class="admin__control-support-text" for="perPage">per page</label> + + <div class="admin__data-grid-pager"> + <button + class="action-previous" + type="button" + data-bind="css: { disabled: isFirst() }, + click: prev"> + <span>Previous page</span> + </button> + <input + id="pageCurrent" + class="admin__control-text" + data-bind="value: _current" + type="number" /> + <label class="admin__control-support-text" for="pageCurrent"> + of <span data-bind="text: pages"></span> + </label> + <button + class="action-next" + data-bind="css: { disabled: isLast() }, + click: next"> + <span>Next page</span> + </button> + </div> + +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/toolbar.html b/app/code/Magento/Ui/view/base/web/templates/grid/toolbar.html new file mode 100644 index 0000000000000000000000000000000000000000..0812e3fe862d2fac42f48fdd80ead31355f23107 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/toolbar.html @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="admin__data-grid-header"> + <div class="admin__data-grid-header-row"> + <div class="admin__data-grid-actions-wrap"> + <!-- ko foreach: getRegion('dataGridActions') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + <!-- ko foreach: getRegion('dataGridFilters') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + <div class="admin__data-grid-header-row row row-gutter"> + <!-- ko foreach: getRegion('bottom') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/group/group.html b/app/code/Magento/Ui/view/base/web/templates/group/group.html index 519aefbcee9f2dae72e0db9fd75f74738d8aeba8..7db2db6edfd14dfb0de0a56abf7ccedc026d1a59 100644 --- a/app/code/Magento/Ui/view/base/web/templates/group/group.html +++ b/app/code/Magento/Ui/view/base/web/templates/group/group.html @@ -4,8 +4,6 @@ * See COPYING.txt for license details. */ --> - -<!-- ko if: element.isMultiple() --> <fieldset class="admin__field" data-bind="css: {'_required': element.required}"> <legend class="admin__field-label"> <span data-bind="text: element.label"></span> @@ -13,14 +11,14 @@ <div class="admin__field-control" data-bind="css: {'admin__control-fields': element.breakLine, 'admin__control-grouped': !element.breakLine}"> <!-- ko foreach: { data: elems, as: 'element' } --> - <!-- ko ifnot: element.hidden --> + <!-- ko if: element.visible() --> <!-- ko ifnot: (element.input_type == 'checkbox' || element.input_type == 'radio') --> <!-- ko template: $parent.fieldTemplate --><!-- /ko --> <!-- /ko --> <!-- ko if: (element.input_type == 'checkbox' || element.input_type == 'radio') --> - <!-- ko template: element.getTemplate() --><!-- /ko --> + <!-- ko template: element.elementTmpl --><!-- /ko --> <!-- /ko --> <!-- /ko --> @@ -28,20 +26,9 @@ <!-- /ko --> <!-- ko foreach: { data: elems, as: 'element' } --> - <!-- ko if: element.error() && !element.hidden() --> + <!-- ko if: element.error() && element.visible() --> <label class="admin__field-error" data-bind="attr: { for: uid }, text: element.error"></label> <!-- /ko --> <!-- /ko --> </div> </fieldset> -<!-- /ko --> - -<!-- ko if: element.isSingle() --> - - <!-- ko foreach: { data: elems, as: 'element' } --> - - <!-- ko template: $parent.fieldTemplate --><!-- /ko --> - - <!-- /ko --> - -<!-- /ko --> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/listing/grid.html b/app/code/Magento/Ui/view/base/web/templates/listing/grid.html deleted file mode 100644 index 6349b6c08e146c12c320bd78e811d9d437fe739d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/listing/grid.html +++ /dev/null @@ -1,36 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<div class="hor-scroll"> - <table class="data"> - <thead data-part="head"> - <tr class="headings" data-part="head.row"> - <!-- ko foreach: { data: fields, as: 'field' } --> - <th> - <span data-bind="text: field.label"></span> - </th> - <!-- /ko --> - </tr> - </thead> - <tbody data-part="body"> - <!-- ko if: hasData() --> - <!-- ko foreach: { data: rows, as: 'row' } --> - <tr data-part="body.row" class="even pointer" data-bind="click: $parent.applyItemActionFor(row)"> - <!-- ko foreach: { data: $parent.fields, as: 'field' } --> - <!-- ko template: $parents[1].getCellTemplateFor(field) --><!-- /ko --> - <!-- /ko --> - </tr> - <!-- /ko --> - <!-- /ko --> - - <!-- ko ifnot: hasData() --> - <tr class="even"> - <td class="empty-text" data-bind="attr: { colspan: colspan }, text: $t('We couldn\'t find any records.')"></td> - </tr> - <!-- /ko --> - </tbody> - </table> -</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/actions.html b/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/actions.html deleted file mode 100644 index 0ebd67b45eecddff54c777e51ee68c6d63380e20..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/actions.html +++ /dev/null @@ -1,16 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td data-part="body.row.cell" data-bind="stopPropagation: true"> - <div data-bind="if: window.Array.isArray(row[field.index])"> - <div data-bind="foreach: { data: row[field.index], as: 'action' }"> - <a target="_blank" data-bind="attr: { href: action.href }, text: action.label"></a> - </div> - </div> - <div data-bind="ifnot: window.Array.isArray(row[field.index])"> - <a target="_blank" data-bind="attr: { href: row[field.index].href }, text: row[field.index].label"></a> - </div> -</td> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/date.html b/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/date.html deleted file mode 100644 index 0bed40dd404be7b7b11bc99a19b57225ec46f6ed..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/date.html +++ /dev/null @@ -1,9 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td data-part="body.row.cell"> - <span data-bind="date: { value: row[field.index], format: field.date_format }"></span> -</td> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/text.html b/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/text.html deleted file mode 100644 index 5ee35346b921d02384022322173b18ea8a0372bb..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/listing/grid/cell/text.html +++ /dev/null @@ -1,14 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td data-part="body.row.cell"> - <span data-bind="'if': 'options' in $data"> - <span data-bind="text: options[row[index]]"></span> - </span> - <span data-bind="ifnot: 'options' in $data"> - <span data-bind="text: row[field.index]"></span> - </span> -</td> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/listing/grid/extender/selectable.html b/app/code/Magento/Ui/view/base/web/templates/listing/grid/extender/selectable.html deleted file mode 100644 index b3a385c92b8fd62b2cdce54188fcecdb5dc15837..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/listing/grid/extender/selectable.html +++ /dev/null @@ -1,38 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<table> - <thead> - <tr data-part-prepend="head.row"> - <th class="col-select col-massaction" data-bind="scope: $parent.getExtender('massaction')"> - <div class="mass-select" data-bind="outerClick: hideMenu, stopPropagation: true"> - <label class="field choice mass-select-field"> - <input type="checkbox" id="mass-select-checkbox" data-bind="checked: allSelected, event: { 'change': toggleSelectAll }"> - </label> - <button class="mass-select-toggle" data-toggle="dropdown" data-bind="css: { 'active': menuVisible }, click: onToggle('menuVisible')"> - <span data-bind="text: $t('Options')"></span> - </button> - <ul class="mass-select-menu" data-bind="css: { 'active': menuVisible } "> - <!-- ko foreach: { data: selects , as: 'action' } --> - <li data-bind="click: $parent.onApplySelect(action.value), visible: $parent.shouldBeVisible(action.value)"> - <span data-bind="text: $t(action.label)"></span> - </li> - <!-- /ko --> - </ul> - </div> - </th> - </tr> - </thead> - <tbody> - <tr data-part-prepend="body.row"> - <td class="col-select col-massaction" data-bind="scope: $parent.getExtender('massaction'), stopPropagation: true"> - <label class="select-box" data-bind="stopPropagation: true"> - <input type="checkbox" class="massaction-checkbox" data-bind="checked: selected, value: row[indexField]"> - </label> - </td> - </tr> - </tbody> -</table> diff --git a/app/code/Magento/Ui/view/base/web/templates/listing/grid/extender/sortable.html b/app/code/Magento/Ui/view/base/web/templates/listing/grid/extender/sortable.html deleted file mode 100644 index 10d0d3f92cd477c62943917ea3846024903d5ed6..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/listing/grid/extender/sortable.html +++ /dev/null @@ -1,25 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<table> - <thead data-part-replace="head" data-bind="scope: getExtender('sorting')"> - <tr class="headings" data-part="head.row"> - <!-- ko foreach: { data: $parent.fields, as: 'field' } --> - <th> - <!-- ko if: field.sortable --> - <span> - <a href="#" data-bind="text: field.label, css: $parent.setClass(field.index), click: $parent.onClick(field)"></a> - </span> - <!-- /ko --> - - <!-- ko ifnot: field.sortable --> - <span data-bind="text: field.label"></span> - <!-- /ko --> - </th> - <!-- /ko --> - </tr> - </thead> -</table> diff --git a/app/code/Magento/Ui/view/base/web/templates/massaction.html b/app/code/Magento/Ui/view/base/web/templates/massaction.html deleted file mode 100644 index 547c92de838807804ce6e2607c2f19b3f0b41dd1..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/massaction.html +++ /dev/null @@ -1,17 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<div title="Select Items" class="actions-split" data-bind="css: {'active': actionsVisible}, stopPropagation: true, outerClick: hideActions"> - <button title="Actions" class="action-default scalable add" data-bind="click: onToggle('actionsVisible')"> - <span data-bind="text: $t('Actions')"></span> - </button> - <button title="" class="action-toggle scalable add" data-toggle="dropdown" data-bind="click: onToggle('actionsVisible'), css: {active: actionsVisible}"> - <span data-bind="text: $t('Select')"></span> - </button> - <ul class="dropdown-menu" data-bind="css: {'active': actionsVisible}, foreach: {data: actions, as: 'action'}"> - <li data-bind="click: $parent.setAction(action)"><span class="item" data-bind="text: label"></span></li> - </ul> -</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/pageactions.html b/app/code/Magento/Ui/view/base/web/templates/pageactions.html deleted file mode 100644 index caf4d917fadfaaa6827f1a25cbd45682bbfa747d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/pageactions.html +++ /dev/null @@ -1,26 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<div class="page-main-actions"> - <div class="page-actions-placeholder"></div> - <div data-mage-init='{"floatingHeader": {}}' class="page-actions" data-ui-id="page-actions-toolbar-content-header"> - <div class="page-actions-inner" data-title="Pages"> - <div class="page-actions-buttons"> - <!-- ko foreach: actions --> - <button data-bind=" - attr: {title: $t(label)}, - css: {primary: type === 'primary'}, - click: $parent.redirectTo(url)" - type="button" - class="action- scalable add" - data-ui-id="cms-page-add-button"> - <span data-bind="text: $t(label)"></span> - </button> - <!-- /ko --> - </div> - </div> - </div> -</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/pagination.html b/app/code/Magento/Ui/view/base/web/templates/pagination.html deleted file mode 100644 index 9046c0f4a1c4b063b7c0df6f04f22d846eae397b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/pagination.html +++ /dev/null @@ -1,32 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<span data-part="left"> - <span class="pages-total-found"> - <strong data-bind="text: totalCount"></strong> records found - <!-- ko if: selected --> - (<strong data-bind="text: selected"></strong> selected) - <!-- /ko --> - </span> - <label class="view-pages"> - View - <select data-bind="options: sizes, value: pageSize, event: { change: onSizeChange}"></select> - per page. - </label> -</span> -<span data-part="right"> - <span data-bind="css: { disabled: isFirst() }, click: prev" class="action-previous"> - <span>Previous page</span> - </span> - <input data-bind="value: current, event: {change: onPageChange}" type="text" class="input-text page" /> - <span class="pages-total"> - of - <span data-bind="text: pages"></span> - </span> - <span data-bind="css: { disabled: isLast() }, click: next" class="action-next"> - <span>Next page</span> - </span> -</span> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/tab.html b/app/code/Magento/Ui/view/base/web/templates/tab.html index d2ff2cd5e890392506e6bae7d6455af70a97965c..8f11fa286ba637260a49d267c52f8f1690e48024 100644 --- a/app/code/Magento/Ui/view/base/web/templates/tab.html +++ b/app/code/Magento/Ui/view/base/web/templates/tab.html @@ -5,8 +5,8 @@ */ --> <div class="admin__page-nav"> - <div class="admin__page-nav-title" data-bind="css: { '_collapsible': collapsible, '_opened': opened() && collapsible }, click: toggle, click: onClick, keyboard: { 13: onClick }"> - <strong tabindex="1" data-bind="text: label, keyboard: { 13: toggle }"></strong> + <div class="admin__page-nav-title" data-bind="css: { '_collapsible': collapsible, '_opened': opened && collapsible }, click: toggleOpened, keyboard: { 13: toggleOpened }"> + <strong tabindex="1" data-bind="text: label, keyboard: { 13: toggleOpened }"></strong> </div> <ul class="admin__page-nav-items items" data-bind="visible: opened"> <!-- ko foreach: elems --> diff --git a/app/code/Magento/Ups/composer.json b/app/code/Magento/Ups/composer.json index 3fed6bdce1e18410c2fc17a53d32f8a93d940f78..d22db469d42c92b9f0b1f004872435abbcc3bf9b 100644 --- a/app/code/Magento/Ups/composer.json +++ b/app/code/Magento/Ups/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/UrlRewrite/composer.json b/app/code/Magento/UrlRewrite/composer.json index 1156b7cb79022a4f0caf8e293c1b752ecc4d0cef..b49e137af5d05c8943bcee48f4e13d54db8c4648 100644 --- a/app/code/Magento/UrlRewrite/composer.json +++ b/app/code/Magento/UrlRewrite/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog-url-rewrite": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-cms-url-rewrite": "0.74.0-beta6", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog-url-rewrite": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-cms-url-rewrite": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Edit.php b/app/code/Magento/User/Controller/Adminhtml/User/Edit.php index 3d3ad64cd201a0bf5cc7eb3691852ab451317e21..39ac43d55391ba02f47089b28233a7f13e791d86 100644 --- a/app/code/Magento/User/Controller/Adminhtml/User/Edit.php +++ b/app/code/Magento/User/Controller/Adminhtml/User/Edit.php @@ -6,6 +6,8 @@ */ namespace Magento\User\Controller\Adminhtml\User; +use Magento\Framework\Locale\Resolver; + class Edit extends \Magento\User\Controller\Adminhtml\User { /** @@ -25,7 +27,7 @@ class Edit extends \Magento\User\Controller\Adminhtml\User return; } } else { - $model->setInterfaceLocale(\Magento\Framework\Locale\ResolverInterface::DEFAULT_LOCALE); + $model->setInterfaceLocale(Resolver::DEFAULT_LOCALE); } // Restore previously entered form data from session diff --git a/app/code/Magento/User/composer.json b/app/code/Magento/User/composer.json index 1d387c17899055557bb811a7c3024d38b90ef587..6c4a9d182196217ea7a011ad8894f37a11884cb4 100644 --- a/app/code/Magento/User/composer.json +++ b/app/code/Magento/User/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-authorization": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-integration": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-authorization": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-integration": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Usps/composer.json b/app/code/Magento/Usps/composer.json index 382961b5610b48750b1aa3e64d77e46433cae688..5e50dcbc46c23ff314332a4aabc477379b318927 100644 --- a/app/code/Magento/Usps/composer.json +++ b/app/code/Magento/Usps/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-shipping": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/module-config": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-shipping": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/module-config": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Variable/composer.json b/app/code/Magento/Variable/composer.json index ececb67d0ec8b20c51576dfe0b271f50a9c98015..87583d867fa2eec4500366d36c5b7cc4363f89cf 100644 --- a/app/code/Magento/Variable/composer.json +++ b/app/code/Magento/Variable/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.4.11|~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta6", - "magento/module-email": "0.74.0-beta6", - "magento/module-store": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-backend": "0.74.0-beta7", + "magento/module-email": "0.74.0-beta7", + "magento/module-store": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Version/composer.json b/app/code/Magento/Version/composer.json index 7bb5e528673b62f88d0c668ab148cdae4dfbcd35..804db0bd8f4ec5d5119b4bfd830bb59eba08f679 100644 --- a/app/code/Magento/Version/composer.json +++ b/app/code/Magento/Version/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Webapi/Controller/Rest/Router/Route.php b/app/code/Magento/Webapi/Controller/Rest/Router/Route.php index 5c125c29611d9e2000436a7147329dfa449ab729..03e6d2fd8ca06eb864bfa318af4a91182e8c1bb7 100644 --- a/app/code/Magento/Webapi/Controller/Rest/Router/Route.php +++ b/app/code/Magento/Webapi/Controller/Rest/Router/Route.php @@ -69,7 +69,7 @@ class Route implements RouterInterface $this->variables[$key] = substr($value, 1); $value = null; } - $result[$key] = strtolower($value); + $result[$key] = $value; } return $result; } @@ -92,19 +92,12 @@ class Route implements RouterInterface /** * Retrieve unified requested path * - * Lowercase all path chunks, except variables names. - * E.g. the path '/V1/Categories/:categoryId' will be converted to '/v1/categories/:categoryId'. - * * @param string $path * @return array */ protected function getPathParts($path) { - $result = explode('/', trim($path, '/')); - array_walk($result, function (&$item) { - $item = substr($item, 0, 1) === ":" ? $item : strtolower($item); - }); - return $result; + return explode('/', trim($path, '/')); } /** diff --git a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php index 25d196ce6a80461109ec3246bbe3a5bb895cfa22..ec73bd7236c104f5364b03433e83d8c622e12414 100644 --- a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php +++ b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php @@ -15,6 +15,7 @@ use Magento\Framework\Webapi\ServiceInputProcessor; use Magento\Webapi\Controller\Soap\Request as SoapRequest; use Magento\Framework\Webapi\Exception as WebapiException; use Magento\Webapi\Model\Soap\Config as SoapConfig; +use Magento\Framework\Reflection\MethodsMap; /** * Handler of requests to SOAP server. @@ -48,6 +49,9 @@ class Handler /** @var DataObjectProcessor */ protected $_dataObjectProcessor; + /** @var MethodsMap */ + protected $methodsMapProcessor; + /** * Initialize dependencies. * @@ -58,6 +62,7 @@ class Handler * @param SimpleDataObjectConverter $dataObjectConverter * @param ServiceInputProcessor $serviceInputProcessor * @param DataObjectProcessor $dataObjectProcessor + * @param MethodsMap $methodsMapProcessor */ public function __construct( SoapRequest $request, @@ -66,7 +71,8 @@ class Handler AuthorizationInterface $authorization, SimpleDataObjectConverter $dataObjectConverter, ServiceInputProcessor $serviceInputProcessor, - DataObjectProcessor $dataObjectProcessor + DataObjectProcessor $dataObjectProcessor, + MethodsMap $methodsMapProcessor ) { $this->_request = $request; $this->_objectManager = $objectManager; @@ -75,6 +81,7 @@ class Handler $this->_dataObjectConverter = $dataObjectConverter; $this->serviceInputProcessor = $serviceInputProcessor; $this->_dataObjectProcessor = $dataObjectProcessor; + $this->methodsMapProcessor = $methodsMapProcessor; } /** @@ -149,7 +156,7 @@ class Handler protected function _prepareResponseData($data, $serviceClassName, $serviceMethodName) { /** @var string $dataType */ - $dataType = $this->_dataObjectProcessor->getMethodReturnType($serviceClassName, $serviceMethodName); + $dataType = $this->methodsMapProcessor->getMethodReturnType($serviceClassName, $serviceMethodName); $result = null; if (is_object($data)) { $result = $this->_dataObjectConverter diff --git a/app/code/Magento/Webapi/Model/Rest/Config.php b/app/code/Magento/Webapi/Model/Rest/Config.php index dfee1d873c02158645f482b3fe7242ecc5636bfe..51d0e67d7803603ef4ff02e6db406f041166b2d9 100644 --- a/app/code/Magento/Webapi/Model/Rest/Config.php +++ b/app/code/Magento/Webapi/Model/Rest/Config.php @@ -67,7 +67,7 @@ class Config /** @var $route \Magento\Webapi\Controller\Rest\Router\Route */ $route = $this->_routeFactory->createRoute( 'Magento\Webapi\Controller\Rest\Router\Route', - $this->_formatRoutePath($routeData[self::KEY_ROUTE_PATH]) + $routeData[self::KEY_ROUTE_PATH] ); $route->setServiceClass($routeData[self::KEY_CLASS]) @@ -78,22 +78,6 @@ class Config return $route; } - /** - * Lowercase all parts of the given route path except for the path parameters. - * - * @param string $routePath The route path (e.g. '/V1/Categories/:categoryId') - * @return string The modified route path (e.g. '/v1/categories/:categoryId') - */ - protected function _formatRoutePath($routePath) - { - $routePathParts = explode('/', $routePath); - $pathParts = []; - foreach ($routePathParts as $pathPart) { - $pathParts[] = substr($pathPart, 0, 1) === ":" ? $pathPart : strtolower($pathPart); - } - return implode('/', $pathParts); - } - /** * Get service base URL * diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/Router/RouteTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/Router/RouteTest.php index 6732d012dc1e726e29e4afab132711759d4ce7f9..4a9192b36882b9f69a66755af08cd3f050374beb 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/Rest/Router/RouteTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/Rest/Router/RouteTest.php @@ -95,10 +95,7 @@ class RouteTest extends \PHPUnit_Framework_TestCase ['/V1/one/two/:threeValue/four/:fiveValue', '/V1/one/two/3/four/5', ['threeValue' => 3, 'fiveValue' => 5]], ['/v1/One', '/v1/One', []], - ['/v1/oNe', '/V1/one', []], - ['/v1/onE', '/V1/oNe', []], - ['/v1/One/:twoValue', '/V1/one/2', ['twoValue' => 2]], ['/v1/oNe/:TwoValue', '/v1/oNe/2', ['TwoValue' => 2]], ['/v1/onE/:twovalue', '/v1/onE/2', ['twovalue' => 2]], @@ -108,6 +105,9 @@ class RouteTest extends \PHPUnit_Framework_TestCase ['/V1/one-one/:two_value', '/V1/one-one/2', ['two_value' => 2]], // Error + ['/v1/oNe', '/V1/one', false], + ['/v1/onE', '/V1/oNe', false], + ['/v1/One/:twoValue', '/V1/one/2', false], ['/V1/one', '/V1/two', false], ['/V1/one/:twoValue', '/V1/one', false], ['/V1/one/two', '/V1/one', false], diff --git a/app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php b/app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php index 2800d5466585fdc8eec97ba82dd53d7f5fee0c93..8c3741c3b8d48c86e0e876125cee6558a2c3a403 100644 --- a/app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Controller/Soap/Request/HandlerTest.php @@ -40,6 +40,9 @@ class HandlerTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Framework\Reflection\DataObjectProcessor|\PHPUnit_Framework_MockObject_MockObject */ protected $_dataObjectProcessorMock; + /** @var \Magento\Framework\Reflection\MethodsMap|\PHPUnit_Framework_MockObject_MockObject */ + protected $_methodsMapProcessorMock; + /** @var array */ protected $_arguments; @@ -67,7 +70,13 @@ class HandlerTest extends \PHPUnit_Framework_TestCase ); $this->_dataObjectProcessorMock = $this->getMock( 'Magento\Framework\Reflection\DataObjectProcessor', - ['getMethodReturnType'], + [], + [], + '', + false); + $this->_methodsMapProcessorMock = $this->getMock( + 'Magento\Framework\Reflection\MethodsMap', + [], [], '', false); @@ -80,7 +89,8 @@ class HandlerTest extends \PHPUnit_Framework_TestCase $this->_authorizationMock, $this->_dataObjectConverter, $this->_serviceInputProcessorMock, - $this->_dataObjectProcessorMock + $this->_dataObjectProcessorMock, + $this->_methodsMapProcessorMock ); parent::setUp(); } @@ -128,10 +138,6 @@ class HandlerTest extends \PHPUnit_Framework_TestCase ->method('process') ->will($this->returnArgument(2)); - $this->_dataObjectProcessorMock->expects($this->any())->method('getMethodReturnType') - ->with($className, $methodName) - ->will($this->returnValue('string')); - /** Execute SUT. */ $this->assertEquals( ['result' => $serviceResponse], diff --git a/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php b/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php index 3453c7e1d7951de030d96012f813477fe73efd4b..c3f586d835a8d3c3d1d85e3626e258680541441c 100644 --- a/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php @@ -23,7 +23,21 @@ class DataObjectProcessorTest extends \PHPUnit_Framework_TestCase protected function setup() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->dataObjectProcessor = $objectManager->getObject('Magento\Framework\Reflection\DataObjectProcessor'); + $methodsMapProcessor = $objectManager->getObject( + 'Magento\Framework\Reflection\MethodsMap', + [ + 'fieldNamer' => $objectManager->getObject('Magento\Framework\Reflection\FieldNamer'), + 'typeProcessor' => $objectManager->getObject('Magento\Framework\Reflection\TypeProcessor'), + ] + ); + $this->dataObjectProcessor = $objectManager->getObject( + 'Magento\Framework\Reflection\DataObjectProcessor', + [ + 'methodsMapProcessor' => $methodsMapProcessor, + 'typeCaster' => $objectManager->getObject('Magento\Framework\Reflection\TypeCaster'), + 'fieldNamer' => $objectManager->getObject('Magento\Framework\Reflection\FieldNamer'), + ] + ); parent::setUp(); } diff --git a/app/code/Magento/Webapi/Test/Unit/Model/Files/TestDataInterface.php b/app/code/Magento/Webapi/Test/Unit/Model/Files/TestDataInterface.php index 1b4f971c2c3a447261a22ce6bb898311813e65b7..2010509ff416165858cbdcb1b1d3b3ae298c9759 100644 --- a/app/code/Magento/Webapi/Test/Unit/Model/Files/TestDataInterface.php +++ b/app/code/Magento/Webapi/Test/Unit/Model/Files/TestDataInterface.php @@ -8,11 +8,23 @@ namespace Magento\Webapi\Test\Unit\Model\Files; interface TestDataInterface { + /** + * @return string + */ public function getId(); + /** + * @return string + */ public function getAddress(); + /** + * @return string + */ public function isDefaultShipping(); + /** + * @return string + */ public function isRequiredBilling(); } diff --git a/app/code/Magento/Webapi/composer.json b/app/code/Magento/Webapi/composer.json index c2e4ec4dacb4f073ed7c35ac5a1a557e8c27db70..4097e63655d1654cbe39c0a5d767abaf613abbcf 100644 --- a/app/code/Magento/Webapi/composer.json +++ b/app/code/Magento/Webapi/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-authorization": "0.74.0-beta6", - "magento/module-integration": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-authorization": "0.74.0-beta7", + "magento/module-integration": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-user": "0.74.0-beta6" + "magento/module-user": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Webapi/etc/di.xml b/app/code/Magento/Webapi/etc/di.xml index 12b661f639c428c681b98b1df7c0f5a8131da632..c58acdbf51c4b9e3252745d425b3d365e2a60449 100644 --- a/app/code/Magento/Webapi/etc/di.xml +++ b/app/code/Magento/Webapi/etc/di.xml @@ -22,11 +22,17 @@ <type name="Magento\Framework\Xml\Parser" shared="false" /> <type name="Magento\Framework\Code\Scanner\DirectoryScanner" shared="false" /> <type name="Magento\Server\Reflection" shared="false" /> - <type name="Magento\Framework\Reflection\DataObjectProcessor"> + <type name="Magento\Framework\Reflection\MethodsMap"> <arguments> <argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Webapi</argument> </arguments> </type> + <type name="Magento\Framework\Reflection\DataObjectProcessor"> + <arguments> + <argument name="extensionAttributesProcessor" xsi:type="object">Magento\Framework\Reflection\ExtensionAttributesProcessor\Proxy</argument> + <argument name="customAttributesProcessor" xsi:type="object">Magento\Framework\Reflection\CustomAttributesProcessor\Proxy</argument> + </arguments> + </type> <type name="Magento\Integration\Model\ConfigBasedIntegrationManager"> <plugin name="webapiSetup" type="Magento\Webapi\Model\Plugin\Manager" /> </type> diff --git a/app/code/Magento/Webapi/etc/webapi_rest/di.xml b/app/code/Magento/Webapi/etc/webapi_rest/di.xml index 48420045d4afca1644c159d3fa68a541cd8c403a..7941e76f564b0fa13986a9847e250a34f36d383c 100644 --- a/app/code/Magento/Webapi/etc/webapi_rest/di.xml +++ b/app/code/Magento/Webapi/etc/webapi_rest/di.xml @@ -71,4 +71,25 @@ <type name="Magento\Framework\Authorization"> <plugin name="guestAuthorization" type="Magento\Webapi\Model\Plugin\GuestAuthorization" /> </type> + + <!-- Configuration to check that the permissions are checked on fields --> + <virtualType name="Magento\Framework\Reflection\ExtensionAttributesProcessorPermissionChecked" type="Magento\Framework\Reflection\ExtensionAttributesProcessor"> + <arguments> + <argument name="isPermissionChecked" xsi:type="boolean">true</argument> + <argument name="dataObjectProcessor" xsi:type="object">Magento\Framework\Reflection\DataObjectProcessor\Proxy</argument> + </arguments> + </virtualType> + <virtualType name="Magento\Framework\Reflection\DataObjectProcessorPermissionChecked" type="Magento\Framework\Reflection\DataObjectProcessor"> + <arguments> + <argument name="extensionAttributesProcessor" xsi:type="object">Magento\Framework\Reflection\ExtensionAttributesProcessorPermissionChecked</argument> + <argument name="customAttributesProcessor" xsi:type="object">Magento\Framework\Reflection\CustomAttributesProcessor\Proxy</argument> + </arguments> + </virtualType> + + <type name="Magento\Framework\Webapi\ServiceOutputProcessor"> + <arguments> + <argument name="dataObjectProcessor" xsi:type="object">Magento\Framework\Reflection\DataObjectProcessorPermissionChecked</argument> + </arguments> + </type> + <!-- End of configuration to check that permissions are checked on fields --> </config> diff --git a/app/code/Magento/Webapi/etc/webapi_soap/di.xml b/app/code/Magento/Webapi/etc/webapi_soap/di.xml index 6d5607c49c18dc46d9e6d9cbc429bc11f4a26467..c8cabfba0ac2529cb3365da99ae129086bee75fe 100644 --- a/app/code/Magento/Webapi/etc/webapi_soap/di.xml +++ b/app/code/Magento/Webapi/etc/webapi_soap/di.xml @@ -39,4 +39,26 @@ <type name="Magento\Framework\Authorization"> <plugin name="guestAuthorization" type="Magento\Webapi\Model\Plugin\GuestAuthorization" /> </type> + + <!-- Configuration to check that the permissions are checked on fields --> + <virtualType name="Magento\Framework\Reflection\ExtensionAttributesProcessorPermissionChecked" type="Magento\Framework\Reflection\ExtensionAttributesProcessor"> + <arguments> + <argument name="isPermissionChecked" xsi:type="boolean">true</argument> + <argument name="dataObjectProcessor" xsi:type="object">Magento\Framework\Reflection\DataObjectProcessor\Proxy</argument> + </arguments> + </virtualType> + <virtualType name="Magento\Framework\Reflection\DataObjectProcessorPermissionChecked" type="Magento\Framework\Reflection\DataObjectProcessor"> + <arguments> + <argument name="extensionAttributesProcessor" xsi:type="object">Magento\Framework\Reflection\ExtensionAttributesProcessorPermissionChecked</argument> + <argument name="customAttributesProcessor" xsi:type="object">Magento\Framework\Reflection\CustomAttributesProcessor\Proxy</argument> + </arguments> + </virtualType> + + <type name="Magento\Webapi\Controller\Soap\Request\Handler"> + <arguments> + <argument name="dataObjectProcessor" xsi:type="object">Magento\Framework\Reflection\DataObjectProcessorPermissionChecked</argument> + </arguments> + </type> + <!-- End of configuration to check that permissions are checked on fields --> + </config> diff --git a/app/code/Magento/Weee/Model/Observer.php b/app/code/Magento/Weee/Model/Observer.php index daca840e903b7e2e8c0f11390a84c259a66ff837..08831d28845bc7fb62e842af1178310da6208160 100644 --- a/app/code/Magento/Weee/Model/Observer.php +++ b/app/code/Magento/Weee/Model/Observer.php @@ -194,4 +194,37 @@ class Observer extends \Magento\Framework\Model\AbstractModel $response->setTypes($types); return $this; } + + /** + * Modify the options config for the front end to resemble the weee final price + * + * @param \Magento\Framework\Event\Observer $observer + * @return $this + */ + public function getPriceConfiguration(\Magento\Framework\Event\Observer $observer) + { + if ($this->_weeeData->isEnabled()) { + $priceConfigObj=$observer->getData('configObj'); + $priceConfig=$priceConfigObj->getConfig(); + if (is_array($priceConfig)) { + foreach ($priceConfig as $keyConfigs => $configs) { + if (is_array($configs)) { + if (array_key_exists('prices', $configs)) { + $priceConfig[$keyConfigs]['prices']['weeePrice'] = [ + 'amount' => $configs['prices']['finalPrice']['amount'], + ]; + } else { + foreach ($configs as $keyConfig => $config) { + $priceConfig[$keyConfigs][$keyConfig]['prices']['weeePrice'] = [ + 'amount' => $config['prices']['finalPrice']['amount'], + ]; + } + } + } + } + } + $priceConfigObj->setConfig($priceConfig); + } + return $this; + } } diff --git a/app/code/Magento/Weee/Pricing/Render/Adjustment.php b/app/code/Magento/Weee/Pricing/Render/Adjustment.php index 2272c719cb94c6b6196e023f0540071693975efb..f13c044532f0514e0c230b8f51ae88b045d060b1 100644 --- a/app/code/Magento/Weee/Pricing/Render/Adjustment.php +++ b/app/code/Magento/Weee/Pricing/Render/Adjustment.php @@ -61,6 +61,14 @@ class Adjustment extends AbstractAdjustment return $this->toHtml(); } + /** + * @return float + */ + public function getRawFinalAmount() + { + return $this->finalAmount; + } + /** * Obtain adjustment code * diff --git a/app/code/Magento/Weee/Test/Unit/Model/ObserverTest.php b/app/code/Magento/Weee/Test/Unit/Model/ObserverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..63a13abb53622e5f93590a1586d695fb17e18707 --- /dev/null +++ b/app/code/Magento/Weee/Test/Unit/Model/ObserverTest.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Test class for \Magento\Weee\Model\Observer + */ +namespace Magento\Weee\Test\Unit\Model; + +use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class ObserverTest extends \PHPUnit_Framework_TestCase +{ + /** + * Tests the methods that rely on the ScopeConfigInterface object to provide their return values + * + */ + public function testGetPriceConfiguration() + { + $testArray=[ + [ + [ + 'prices' => + [ + 'finalPrice' => [ + 'amount' => 31.50, + ], + ], + ], + [ + 'prices' => + [ + 'finalPrice' =>[ + 'amount' => 31.50, + ], + ], + ], + ], + ]; + + $configObj = new \Magento\Framework\Object( + [ + 'config' => $testArray, + ] + ); + + $testArrayWithWeee=$testArray; + $testArrayWithWeee[0][0]['prices']['weeePrice']= [ + 'amount' => $testArray[0][0]['prices']['finalPrice']['amount'], + ]; + $testArrayWithWeee[0][1]['prices']['weeePrice']= [ + 'amount' => $testArray[0][1]['prices']['finalPrice']['amount'], + ]; + + $weeHelper=$this->getMock('Magento\Weee\Helper\Data', [], [], '', false); + $weeHelper->expects($this->any()) + ->method('isEnabled') + ->will($this->returnValue(true)); + + $observerObject=$this->getMock('Magento\Framework\Event\Observer', [], [], '', false); + + $observerObject->expects($this->any()) + ->method('getData') + ->with('configObj') + ->will($this->returnValue($configObj)); + + $objectManager = new ObjectManager($this); + $weeeObserverObject = $objectManager->getObject( + 'Magento\Weee\Model\Observer', + [ + 'weeeData' => $weeHelper, + ] + ); + $weeeObserverObject->getPriceConfiguration($observerObject); + + $this->assertEquals($testArrayWithWeee, $configObj->getData('config')); + } +} diff --git a/app/code/Magento/Weee/composer.json b/app/code/Magento/Weee/composer.json index 9b11852f84fd425b09a62737597c797ddcdd31d8..ba4b15374bad4320414343956952ec2ac5fd3000 100644 --- a/app/code/Magento/Weee/composer.json +++ b/app/code/Magento/Weee/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-tax": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-directory": "0.74.0-beta6", - "magento/module-eav": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-quote": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-tax": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-directory": "0.74.0-beta7", + "magento/module-eav": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-quote": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Weee/etc/events.xml b/app/code/Magento/Weee/etc/events.xml index b6ef0f804b1fd72258baff580d5257b90dd1a31e..f4300f38b2369817d96c1902c29c57d378676f17 100644 --- a/app/code/Magento/Weee/etc/events.xml +++ b/app/code/Magento/Weee/etc/events.xml @@ -9,4 +9,7 @@ <event name="catalog_entity_attribute_save_before"> <observer name="weee" instance="Magento\Weee\Model\Observer" method="assignBackendModelToAttribute" shared="false" /> </event> + <event name="catalog_product_option_price_configuration_after"> + <observer name="weee" instance="Magento\Weee\Model\Observer" method="getPriceConfiguration" shared="false" /> + </event> </config> diff --git a/app/code/Magento/Weee/view/base/templates/pricing/adjustment.phtml b/app/code/Magento/Weee/view/base/templates/pricing/adjustment.phtml index 86267dea51a757c481bff1d110c6ce121cd41a5e..f8a77699ff4d9356fa99cf9eed5925efbc1b3a3d 100644 --- a/app/code/Magento/Weee/view/base/templates/pricing/adjustment.phtml +++ b/app/code/Magento/Weee/view/base/templates/pricing/adjustment.phtml @@ -28,5 +28,7 @@ $closeBrace = ')'; data-label="<?php echo $block->renderWeeeTaxAttributeName($weeeTaxAttribute); ?>"><?php echo $block->renderWeeeTaxAttribute($weeeTaxAttribute); ?></span> <?php endforeach; ?> <span class="price-final_price" + data-price-type="weeePrice" + data-price-amount="<?php echo $block->getRawFinalAmount(); ?>" data-label="<?php echo __('Final Price'); ?>"><?php echo $block->getFinalAmount(); ?></span> <?php endif; ?> diff --git a/app/code/Magento/Widget/composer.json b/app/code/Magento/Widget/composer.json index e1ebbafa7d489f3a823f28fee6e691289851c00b..3cf33ee5654bfca968013901005b5e9157b0abcc 100644 --- a/app/code/Magento/Widget/composer.json +++ b/app/code/Magento/Widget/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-cms": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-variable": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-cms": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-variable": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php b/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php index 2f393bf6d2c40e0d1e80974d5854187c8bd994df..6a6d83a1bdabef4d2d3f7d7c47b50a9c157b574a 100644 --- a/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php +++ b/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php @@ -5,17 +5,16 @@ */ namespace Magento\Wishlist\Block\Adminhtml; -use Magento\Backend\Block\Template\Context; -use Magento\Customer\Controller\RegistryConstants; use Magento\Framework\Registry; +use Magento\Backend\Block\Template\Context; use Magento\Ui\Component\Layout\Tabs\TabWrapper; +use Magento\Ui\Component\Layout\Tabs\TabInterface; +use Magento\Customer\Controller\RegistryConstants; /** * Class WishlistTab - * - * @package Magento\Wishlist\Block\Adminhtml */ -class WishlistTab extends TabWrapper +class WishlistTab extends TabWrapper implements TabInterface { /** * Core registry diff --git a/app/code/Magento/Wishlist/Controller/Index/Add.php b/app/code/Magento/Wishlist/Controller/Index/Add.php index 5adebd054bbefa21b0b84c0147be8988fd6a0ad9..3f307ad116dd84ad63d0befb0adde4a4919654a7 100755 --- a/app/code/Magento/Wishlist/Controller/Index/Add.php +++ b/app/code/Magento/Wishlist/Controller/Index/Add.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -11,6 +10,7 @@ use Magento\Framework\App\Action; use Magento\Framework\Exception\NotFoundException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class Add extends Action\Action implements IndexInterface { @@ -50,7 +50,7 @@ class Add extends Action\Action implements IndexInterface /** * Adding new item * - * @return void + * @return \Magento\Framework\Controller\Result\Redirect * @throws NotFoundException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) @@ -73,10 +73,11 @@ class Add extends Action\Action implements IndexInterface } $productId = isset($requestParams['product']) ? (int)$requestParams['product'] : null; - + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); if (!$productId) { - $this->_redirect('*/'); - return; + $resultRedirect->setPath('*/'); + return $resultRedirect; } try { @@ -87,8 +88,8 @@ class Add extends Action\Action implements IndexInterface if (!$product || !$product->isVisibleInCatalog()) { $this->messageManager->addError(__('We can\'t specify a product.')); - $this->_redirect('*/'); - return; + $resultRedirect->setPath('*/'); + return $resultRedirect; } try { @@ -112,9 +113,7 @@ class Add extends Action\Action implements IndexInterface $referer = $this->_redirect->getRefererUrl(); } - - /** @var $helper \Magento\Wishlist\Helper\Data */ - $helper = $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate(); + $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate(); $message = __( '%1 has been added to your wishlist. Click <a href="%2">here</a> to continue shopping.', $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($product->getName()), @@ -130,6 +129,7 @@ class Add extends Action\Action implements IndexInterface $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } - $this->_redirect('*', ['wishlist_id' => $wishlist->getId()]); + $resultRedirect->setPath('*', ['wishlist_id' => $wishlist->getId()]); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Allcart.php b/app/code/Magento/Wishlist/Controller/Index/Allcart.php index fa7720947034110bf0d80155aa23b7d08960498d..7cf5a187a5687bace697d03101e9ad7e78c8b8c3 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Allcart.php +++ b/app/code/Magento/Wishlist/Controller/Index/Allcart.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -12,6 +11,7 @@ use Magento\Framework\App\Action\Context; use Magento\Wishlist\Controller\IndexInterface; use Magento\Wishlist\Controller\WishlistProviderInterface; use Magento\Wishlist\Model\ItemCarrier; +use Magento\Framework\Controller\ResultFactory; class Allcart extends Action\Action implements IndexInterface { @@ -51,21 +51,26 @@ class Allcart extends Action\Action implements IndexInterface /** * Add all items from wishlist to shopping cart * - * @return void + * @return \Magento\Framework\Controller\ResultInterface */ public function execute() { + /** @var \Magento\Framework\Controller\Result\Forward $resultForward */ + $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD); if (!$this->formKeyValidator->validate($this->getRequest())) { - $this->_forward('noroute'); - return; + $resultForward->forward('noroute'); + return $resultForward; } $wishlist = $this->wishlistProvider->getWishlist(); if (!$wishlist) { - $this->_forward('noroute'); - return; + $resultForward->forward('noroute'); + return $resultForward; } + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $redirectUrl = $this->itemCarrier->moveAllToCart($wishlist, $this->getRequest()->getParam('qty')); - $this->getResponse()->setRedirect($redirectUrl); + $resultRedirect->setUrl($redirectUrl); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Cart.php b/app/code/Magento/Wishlist/Controller/Index/Cart.php index 61a80f8ca58ee312f0bbf5d1572b86c15395b383..5274e565c1b029777fdc7d6ec9d8753f5e7d64dc 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Cart.php +++ b/app/code/Magento/Wishlist/Controller/Index/Cart.php @@ -1,15 +1,14 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; -use Magento\Framework\App\ResponseInterface; use Magento\Wishlist\Controller\IndexInterface; use Magento\Catalog\Model\Product\Exception as ProductException; +use Magento\Framework\Controller\ResultFactory; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -41,11 +40,6 @@ class Cart extends Action\Action implements IndexInterface */ protected $cartHelper; - /** - * @var \Magento\Framework\Json\Helper\Data - */ - protected $jsonHelper; - /** * @var \Magento\Wishlist\Model\Item\OptionFactory */ @@ -77,8 +71,6 @@ class Cart extends Action\Action implements IndexInterface * @param \Magento\Framework\Escaper $escaper * @param \Magento\Wishlist\Helper\Data $helper * @param \Magento\Checkout\Helper\Cart $cartHelper - * @param \Magento\Framework\Json\Helper\Data $jsonHelper - * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -91,8 +83,7 @@ class Cart extends Action\Action implements IndexInterface \Magento\Catalog\Helper\Product $productHelper, \Magento\Framework\Escaper $escaper, \Magento\Wishlist\Helper\Data $helper, - \Magento\Checkout\Helper\Cart $cartHelper, - \Magento\Framework\Json\Helper\Data $jsonHelper + \Magento\Checkout\Helper\Cart $cartHelper ) { $this->wishlistProvider = $wishlistProvider; $this->quantityProcessor = $quantityProcessor; @@ -103,7 +94,6 @@ class Cart extends Action\Action implements IndexInterface $this->escaper = $escaper; $this->helper = $helper; $this->cartHelper = $cartHelper; - $this->jsonHelper = $jsonHelper; parent::__construct($context); } @@ -113,22 +103,25 @@ class Cart extends Action\Action implements IndexInterface * If Product has required options - item removed from wishlist and redirect * to product view page with message about needed defined required options * - * @return ResponseInterface + * @return \Magento\Framework\Controller\ResultInterface * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function execute() { $itemId = (int)$this->getRequest()->getParam('item'); - + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); /* @var $item \Magento\Wishlist\Model\Item */ $item = $this->itemFactory->create()->load($itemId); if (!$item->getId()) { - return $this->_redirect('*/*'); + $resultRedirect->setPath('*/*'); + return $resultRedirect; } $wishlist = $this->wishlistProvider->getWishlist($item->getWishlistId()); if (!$wishlist) { - return $this->_redirect('*/*'); + $resultRedirect->setPath('*/*'); + return $resultRedirect; } // Set qty @@ -197,12 +190,13 @@ class Cart extends Action\Action implements IndexInterface $this->helper->calculate(); if ($this->getRequest()->isAjax()) { - $this->getResponse()->representJson( - $this->jsonHelper->jsonEncode(['backUrl' => $redirectUrl]) - ); - return; + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData(['backUrl' => $redirectUrl]); + return $resultJson; } - - return $this->getResponse()->setRedirect($redirectUrl); + + $resultRedirect->setUrl($redirectUrl); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Configure.php b/app/code/Magento/Wishlist/Controller/Index/Configure.php index 8172c895ed70e361cdeff01b31484bd69917a396..37522cd4cd0dac0bf1719106db853dbba4190744 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Configure.php +++ b/app/code/Magento/Wishlist/Controller/Index/Configure.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +8,7 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Framework\Exception\NotFoundException; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class Configure extends Action\Action implements IndexInterface { @@ -50,12 +50,14 @@ class Configure extends Action\Action implements IndexInterface /** * Action to reconfigure wishlist item * - * @return void + * @return \Magento\Framework\Controller\ResultInterface * @throws NotFoundException */ public function execute() { $id = (int)$this->getRequest()->getParam('id'); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); try { /* @var $item \Magento\Wishlist\Model\Item */ $item = $this->_objectManager->create('Magento\Wishlist\Model\Item'); @@ -83,7 +85,7 @@ class Configure extends Action\Action implements IndexInterface } $params->setBuyRequest($buyRequest); /** @var \Magento\Framework\View\Result\Page $resultPage */ - $resultPage = $this->resultPageFactory->create(); + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); $this->_objectManager->get( 'Magento\Catalog\Helper\Product\View' )->prepareAndRender( @@ -96,13 +98,13 @@ class Configure extends Action\Action implements IndexInterface return $resultPage; } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); - $this->_redirect('*'); - return; + $resultRedirect->setPath('*'); + return $resultRedirect; } catch (\Exception $e) { $this->messageManager->addError(__('We can\'t configure the product.')); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); - $this->_redirect('*'); - return; + $resultRedirect->setPath('*'); + return $resultRedirect; } } } diff --git a/app/code/Magento/Wishlist/Controller/Index/DownloadCustomOption.php b/app/code/Magento/Wishlist/Controller/Index/DownloadCustomOption.php index 3c26bf8e64db6f7007b465927d10622f2e5a3816..1edd5e4426ee0343e25a9ab270674e72c74a4b79 100644 --- a/app/code/Magento/Wishlist/Controller/Index/DownloadCustomOption.php +++ b/app/code/Magento/Wishlist/Controller/Index/DownloadCustomOption.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +8,7 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class DownloadCustomOption extends Action\Action implements IndexInterface { @@ -32,7 +32,7 @@ class DownloadCustomOption extends Action\Action implements IndexInterface /** * Custom options download action * - * @return void + * @return \Magento\Framework\Controller\Result\Forward * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExitExpression) */ @@ -43,9 +43,11 @@ class DownloadCustomOption extends Action\Action implements IndexInterface )->load( $this->getRequest()->getParam('id') ); - + /** @var \Magento\Framework\Controller\Result\Forward $resultForward */ + $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD); if (!$option->getId()) { - return $this->_forward('noroute'); + $resultForward->forward('noroute'); + return $resultForward; } $optionId = null; @@ -56,7 +58,8 @@ class DownloadCustomOption extends Action\Action implements IndexInterface $option->getCode() ); if ((int)$optionId != $optionId) { - return $this->_forward('noroute'); + $resultForward->forward('noroute'); + return $resultForward; } } $productOption = $this->_objectManager->create('Magento\Catalog\Model\Product\Option')->load($optionId); @@ -66,7 +69,8 @@ class DownloadCustomOption extends Action\Action implements IndexInterface $productOption->getProductId() != $option->getProductId() || $productOption->getType() != 'file' ) { - return $this->_forward('noroute'); + $resultForward->forward('noroute'); + return $resultForward; } try { @@ -81,8 +85,8 @@ class DownloadCustomOption extends Action\Action implements IndexInterface ); } } catch (\Exception $e) { - $this->_forward('noroute'); + $resultForward->forward('noroute'); + return $resultForward; } - exit(0); } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Fromcart.php b/app/code/Magento/Wishlist/Controller/Index/Fromcart.php index 085cf426a0a37cacae5decf0bfa6e020e229b6fb..03c1db81044f7b1be83ea1d319a4614538f9395f 100755 --- a/app/code/Magento/Wishlist/Controller/Index/Fromcart.php +++ b/app/code/Magento/Wishlist/Controller/Index/Fromcart.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +8,7 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Framework\Exception\NotFoundException; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class Fromcart extends Action\Action implements IndexInterface { @@ -82,7 +82,8 @@ class Fromcart extends Action\Action implements IndexInterface */ public function getDefaultResult() { - $resultRedirect = $this->resultRedirectFactory->create(); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setUrl($this->_objectManager->get('Magento\Checkout\Helper\Cart')->getCartUrl()); } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Index.php b/app/code/Magento/Wishlist/Controller/Index/Index.php index 9cb4bbe9fcdb089edab3d242f6a648b128c55890..53566774d2400ee6dd73f7468bd4fb1de3d10c49 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Index.php +++ b/app/code/Magento/Wishlist/Controller/Index/Index.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +8,7 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Framework\Exception\NotFoundException; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class Index extends Action\Action implements IndexInterface { @@ -32,7 +32,7 @@ class Index extends Action\Action implements IndexInterface /** * Display customer wishlist * - * @return void + * @return \Magento\Framework\View\Result\Page * @throws NotFoundException */ public function execute() @@ -40,8 +40,9 @@ class Index extends Action\Action implements IndexInterface if (!$this->wishlistProvider->getWishlist()) { throw new NotFoundException(__('Page not found.')); } - $this->_view->loadLayout(); - $this->_view->getLayout()->initMessages(); - $this->_view->renderLayout(); + /** @var \Magento\Framework\View\Result\Page resultPage */ + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->getLayout()->initMessages(); + return $resultPage; } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Remove.php b/app/code/Magento/Wishlist/Controller/Index/Remove.php index 674d1118a614689e2c25958bb205c3eb5be668ae..6a07bcbc9e03b6634f6c7d08fd7563e1650493ea 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Remove.php +++ b/app/code/Magento/Wishlist/Controller/Index/Remove.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -9,6 +8,7 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Framework\Exception\NotFoundException; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class Remove extends Action\Action implements IndexInterface { @@ -32,7 +32,7 @@ class Remove extends Action\Action implements IndexInterface /** * Remove item * - * @return void + * @return \Magento\Framework\Controller\Result\Redirect * @throws NotFoundException */ public function execute() @@ -69,6 +69,9 @@ class Remove extends Action\Action implements IndexInterface } else { $redirectUrl = $this->_redirect->getRedirectUrl($this->_url->getUrl('*/*')); } - $this->getResponse()->setRedirect($redirectUrl); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setUrl($redirectUrl); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Send.php b/app/code/Magento/Wishlist/Controller/Index/Send.php index 6a54e1b7bf9f0ba2da61da6f0976f40f0ab81b9a..591da81b0aab9f36ebcd3654bf5290fa91b11242 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Send.php +++ b/app/code/Magento/Wishlist/Controller/Index/Send.php @@ -8,8 +8,9 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Framework\Exception\NotFoundException; -use Magento\Framework\App\ResponseInterface; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\View\Result\Layout as ResultLayout; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -84,7 +85,7 @@ class Send extends Action\Action implements IndexInterface /** * Share wishlist * - * @return ResponseInterface|void + * @return \Magento\Framework\Controller\Result\Redirect * @throws NotFoundException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) @@ -92,8 +93,11 @@ class Send extends Action\Action implements IndexInterface */ public function execute() { + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); if (!$this->_formKeyValidator->validate($this->getRequest())) { - return $this->_redirect('*/*/'); + $resultRedirect->setPath('*/*/'); + return $resultRedirect; } $wishlist = $this->wishlistProvider->getWishlist(); @@ -136,11 +140,12 @@ class Send extends Action\Action implements IndexInterface )->setSharingForm( $this->getRequest()->getPostValue() ); - $this->_redirect('*/*/share'); - return; + $resultRedirect->setPath('*/*/share'); + return $resultRedirect; } - - $this->addLayoutHandles(); + /** @var \Magento\Framework\View\Result\Layout $resultLayout */ + $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT); + $this->addLayoutHandles($resultLayout); $this->inlineTranslation->suspend(); $sent = 0; @@ -149,7 +154,7 @@ class Send extends Action\Action implements IndexInterface $customer = $this->_customerSession->getCustomerDataObject(); $customerName = $this->_customerHelperView->getCustomerName($customer); - $message .= $this->getRssLink($wishlist->getId()); + $message .= $this->getRssLink($wishlist->getId(), $resultLayout); $emails = array_unique($emails); $sharingCode = $wishlist->getSharingCode(); @@ -172,7 +177,7 @@ class Send extends Action\Action implements IndexInterface 'customer' => $customer, 'customerName' => $customerName, 'salable' => $wishlist->isSalable() ? 'yes' : '', - 'items' => $this->getWishlistItems(), + 'items' => $this->getWishlistItems($resultLayout), 'addAllLink' => $this->_url->getUrl('*/shared/allcart', ['code' => $sharingCode]), 'viewOnSiteLink' => $this->_url->getUrl('*/shared/index', ['code' => $sharingCode]), 'message' => $message, @@ -203,7 +208,8 @@ class Send extends Action\Action implements IndexInterface $this->_eventManager->dispatch('wishlist_share', ['wishlist' => $wishlist]); $this->messageManager->addSuccess(__('Your wish list has been shared.')); - $this->_redirect('*/*', ['wishlist_id' => $wishlist->getId()]); + $resultRedirect->setPath('*/*', ['wishlist_id' => $wishlist->getId()]); + return $resultRedirect; } catch (\Exception $e) { $this->inlineTranslation->resume(); $this->messageManager->addError($e->getMessage()); @@ -212,7 +218,8 @@ class Send extends Action\Action implements IndexInterface )->setSharingForm( $this->getRequest()->getPostValue() ); - $this->_redirect('*/*/share'); + $resultRedirect->setPath('*/*/share'); + return $resultRedirect; } } @@ -222,27 +229,28 @@ class Send extends Action\Action implements IndexInterface * Add 'wishlist_email_rss' layout handle. * Add 'wishlist_email_items' layout handle. * + * @param \Magento\Framework\View\Result\Layout $resultLayout * @return void */ - protected function addLayoutHandles() + protected function addLayoutHandles(ResultLayout $resultLayout) { if ($this->getRequest()->getParam('rss_url')) { - $this->_view->getLayout()->getUpdate()->addHandle('wishlist_email_rss'); + $resultLayout->addHandle('wishlist_email_rss'); } - $this->_view->getLayout()->getUpdate()->addHandle('wishlist_email_items'); - $this->_view->loadLayoutUpdates(); + $resultLayout->addHandle('wishlist_email_items'); } /** * Retrieve RSS link content (html) * * @param int $wishlistId + * @param \Magento\Framework\View\Result\Layout $resultLayout * @return mixed */ - protected function getRssLink($wishlistId) + protected function getRssLink($wishlistId, ResultLayout $resultLayout) { if ($this->getRequest()->getParam('rss_url')) { - return $this->_view->getLayout() + return $resultLayout->getLayout() ->getBlock('wishlist.email.rss') ->setWishlistId($wishlistId) ->toHtml(); @@ -252,11 +260,12 @@ class Send extends Action\Action implements IndexInterface /** * Retrieve wishlist items content (html) * + * @param \Magento\Framework\View\Result\Layout $resultLayout * @return string */ - protected function getWishlistItems() + protected function getWishlistItems(ResultLayout $resultLayout) { - return $this->_view->getLayout() + return $resultLayout->getLayout() ->getBlock('wishlist.email.items') ->toHtml(); } diff --git a/app/code/Magento/Wishlist/Controller/Index/Share.php b/app/code/Magento/Wishlist/Controller/Index/Share.php index b47a0027f7bdd793ebef983e69aaae1f8861c651..cfc8f8a7f8b2a51cfc3a2e8f120735c4c449ac5f 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Share.php +++ b/app/code/Magento/Wishlist/Controller/Index/Share.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,18 +7,20 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class Share extends Action\Action implements IndexInterface { /** * Prepare wishlist for share * - * @return void + * @return \Magento\Framework\View\Result\Page */ public function execute() { - $this->_view->loadLayout(); - $this->_view->getLayout()->initMessages(); - $this->_view->renderLayout(); + /** @var \Magento\Framework\View\Result\Page $resultPage */ + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->getLayout()->initMessages(); + return $resultPage; } } diff --git a/app/code/Magento/Wishlist/Controller/Index/Update.php b/app/code/Magento/Wishlist/Controller/Index/Update.php index 731a80cd743570abb624ee89bee2fb5a2e5179eb..ab7c5efd3d88aaf958418273106c46d66cf1b0e6 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Update.php +++ b/app/code/Magento/Wishlist/Controller/Index/Update.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,8 +7,8 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; use Magento\Framework\Exception\NotFoundException; -use Magento\Framework\App\ResponseInterface; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class Update extends Action\Action implements IndexInterface { @@ -49,15 +48,18 @@ class Update extends Action\Action implements IndexInterface /** * Update wishlist item comments * - * @return ResponseInterface|void + * @return \Magento\Framework\Controller\Result\Redirect * @throws NotFoundException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function execute() { + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); if (!$this->_formKeyValidator->validate($this->getRequest())) { - return $this->_redirect('*/*/'); + $resultRedirect->setPath('*/*/'); + return $resultRedirect; } $wishlist = $this->wishlistProvider->getWishlist(); if (!$wishlist) { @@ -130,10 +132,11 @@ class Update extends Action\Action implements IndexInterface } if (isset($post['save_and_share'])) { - $this->_redirect('*/*/share', ['wishlist_id' => $wishlist->getId()]); - return; + $resultRedirect->setPath('*/*/share', ['wishlist_id' => $wishlist->getId()]); + return $resultRedirect; } } - $this->_redirect('*', ['wishlist_id' => $wishlist->getId()]); + $resultRedirect->setPath('*', ['wishlist_id' => $wishlist->getId()]); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php b/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php index 483d3793eddc7fb3b0b107a8978e3143a3ca2897..b9dee182873329586d901c6fd32ca9e18116fd95 100644 --- a/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php +++ b/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -10,6 +9,7 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\App\Action; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Wishlist\Controller\IndexInterface; +use Magento\Framework\Controller\ResultFactory; class UpdateItemOptions extends Action\Action implements IndexInterface { @@ -49,14 +49,16 @@ class UpdateItemOptions extends Action\Action implements IndexInterface /** * Action to accept new configuration for a wishlist item * - * @return void + * @return \Magento\Framework\Controller\Result\Redirect */ public function execute() { $productId = (int)$this->getRequest()->getParam('product'); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); if (!$productId) { - $this->_redirect('*/'); - return; + $resultRedirect->setPath('*/'); + return $resultRedirect; } try { @@ -67,8 +69,8 @@ class UpdateItemOptions extends Action\Action implements IndexInterface if (!$product || !$product->isVisibleInCatalog()) { $this->messageManager->addError(__('We can\'t specify a product.')); - $this->_redirect('*/'); - return; + $resultRedirect->setPath('*/'); + return $resultRedirect; } try { @@ -78,8 +80,8 @@ class UpdateItemOptions extends Action\Action implements IndexInterface $item->load($id); $wishlist = $this->wishlistProvider->getWishlist($item->getWishlistId()); if (!$wishlist) { - $this->_redirect('*/'); - return; + $resultRedirect->setPath('*/'); + return $resultRedirect; } $buyRequest = new \Magento\Framework\Object($this->getRequest()->getParams()); @@ -102,6 +104,7 @@ class UpdateItemOptions extends Action\Action implements IndexInterface $this->messageManager->addError(__('An error occurred while updating wish list.')); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } - $this->_redirect('*/*', ['wishlist_id' => $wishlist->getId()]); + $resultRedirect->setPath('*/*', ['wishlist_id' => $wishlist->getId()]); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Shared/Allcart.php b/app/code/Magento/Wishlist/Controller/Shared/Allcart.php index 27dc5d8fd5d94bb56e9060035a136c6d30a6c368..ffb6e34ea96390aedd403549f7294126bcd1b93c 100644 --- a/app/code/Magento/Wishlist/Controller/Shared/Allcart.php +++ b/app/code/Magento/Wishlist/Controller/Shared/Allcart.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,6 +7,7 @@ namespace Magento\Wishlist\Controller\Shared; use Magento\Framework\App\Action\Context; use Magento\Wishlist\Model\ItemCarrier; +use Magento\Framework\Controller\ResultFactory; class Allcart extends \Magento\Framework\App\Action\Action { @@ -39,16 +39,21 @@ class Allcart extends \Magento\Framework\App\Action\Action /** * Add all items from wishlist to shopping cart * - * @return void + * @return \Magento\Framework\Controller\ResultInterface */ public function execute() { $wishlist = $this->wishlistProvider->getWishlist(); if (!$wishlist) { - $this->_forward('noroute'); - return; + /** @var \Magento\Framework\Controller\Result\Forward $resultForward */ + $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD); + $resultForward->forward('noroute'); + return $resultForward; } $redirectUrl = $this->itemCarrier->moveAllToCart($wishlist, $this->getRequest()->getParam('qty')); - $this->getResponse()->setRedirect($redirectUrl); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setUrl($redirectUrl); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Shared/Cart.php b/app/code/Magento/Wishlist/Controller/Shared/Cart.php index b14e996706ec4892296df08cad1b777c1166a41b..5c1efa80aec9ed522b32785b837805a0c05ab120 100644 --- a/app/code/Magento/Wishlist/Controller/Shared/Cart.php +++ b/app/code/Magento/Wishlist/Controller/Shared/Cart.php @@ -1,11 +1,12 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Wishlist\Controller\Shared; +use Magento\Framework\Controller\ResultFactory; + class Cart extends \Magento\Framework\App\Action\Action { /** @@ -14,7 +15,7 @@ class Cart extends \Magento\Framework\App\Action\Action * If Product has required options - redirect * to product view page with message about needed defined required options * - * @return \Magento\Framework\App\Response\Http + * @return \Magento\Framework\Controller\Result\Redirect */ public function execute() { @@ -51,7 +52,9 @@ class Cart extends \Magento\Framework\App\Action\Action } catch (\Exception $e) { $this->messageManager->addException($e, __('Cannot add item to shopping cart')); } - - return $this->getResponse()->setRedirect($redirectUrl); + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setUrl($redirectUrl); + return $resultRedirect; } } diff --git a/app/code/Magento/Wishlist/Controller/Shared/Index.php b/app/code/Magento/Wishlist/Controller/Shared/Index.php index 39c564d62004792cff56a7c3a6f81e510cb4e3ba..20ccbf1b45bcf38e17a0df3b09849da725a3ec5e 100644 --- a/app/code/Magento/Wishlist/Controller/Shared/Index.php +++ b/app/code/Magento/Wishlist/Controller/Shared/Index.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,8 +7,9 @@ namespace Magento\Wishlist\Controller\Shared; use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; +use Magento\Framework\Controller\ResultFactory; -class Index extends \Magento\Framework\App\Action\Action +class Index extends Action { /** * Core registry @@ -49,7 +49,7 @@ class Index extends \Magento\Framework\App\Action\Action /** * Shared wishlist view page * - * @return void + * @return \Magento\Framework\Controller\ResultInterface */ public function execute() { @@ -57,16 +57,18 @@ class Index extends \Magento\Framework\App\Action\Action $customerId = $this->customerSession->getCustomerId(); if ($wishlist && $wishlist->getCustomerId() && $wishlist->getCustomerId() == $customerId) { - $this->getResponse()->setRedirect( + /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setUrl( $this->_objectManager->get('Magento\Wishlist\Helper\Data')->getListUrl($wishlist->getId()) ); - return; + return $resultRedirect; } $this->registry->register('shared_wishlist', $wishlist); - - $this->_view->loadLayout(); - $this->_view->getLayout()->initMessages(); - $this->_view->renderLayout(); + /** @var \Magento\Framework\View\Result\Page $resultPage */ + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->getLayout()->initMessages(); + return $resultPage; } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php index 98fbbc933f8a1da2f837a85079624e6ce180a314..54e91fb5f079aad57ac236a3ee64c9c87f675b4b 100755 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php @@ -3,9 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\Test\Unit\Controller\Index; +use Magento\Framework\Controller\ResultFactory; + class AddTest extends \PHPUnit_Framework_TestCase { /** @@ -33,21 +34,21 @@ class AddTest extends \PHPUnit_Framework_TestCase */ protected $controller; + /** + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultFactoryMock; + + /** + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRedirectMock; + public function setUp() { $this->context = $this->getMock( 'Magento\Framework\App\Action\Context', - [ - 'getRequest', - 'getResponse', - 'getObjectManager', - 'getEventManager', - 'getUrl', - 'getActionFlag', - 'getRedirect', - 'getView', - 'getMessageManager' - ], + [], [], '', false @@ -79,6 +80,17 @@ class AddTest extends \PHPUnit_Framework_TestCase '', false ); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactoryMock->expects($this->any()) + ->method('create') + ->with(ResultFactory::TYPE_REDIRECT, []) + ->willReturn($this->resultRedirectMock); } /** @@ -128,13 +140,6 @@ class AddTest extends \PHPUnit_Framework_TestCase '', false ); - $redirect = $this->getMock( - '\Magento\Store\App\Response\Redirect', - null, - [], - '', - false - ); $view = $this->getMock( 'Magento\Framework\App\View', null, @@ -174,10 +179,6 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getActionFlag') ->will($this->returnValue($actionFlag)); - $this->context - ->expects($this->any()) - ->method('getRedirect') - ->will($this->returnValue($redirect)); $this->context ->expects($this->any()) ->method('getView') @@ -186,6 +187,9 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getMessageManager') ->will($this->returnValue($messageManager)); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); } public function configureCustomerSession() @@ -261,12 +265,10 @@ class AddTest extends \PHPUnit_Framework_TestCase $eventManager = $this->getMock('Magento\Framework\Event\Manager', null, [], '', false); $url = $this->getMock('Magento\Framework\Url', null, [], '', false); $actionFlag = $this->getMock('Magento\Framework\App\ActionFlag', null, [], '', false); - $redirect = $this->getMock('\Magento\Store\App\Response\Redirect', ['redirect'], [], '', false); - $redirect - ->expects($this->once()) - ->method('redirect') - ->with($response, '*/', []) - ->will($this->returnValue(null)); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/', []) + ->willReturnSelf(); $view = $this->getMock('Magento\Framework\App\View', null, [], '', false); $messageManager = $this->getMock('Magento\Framework\Message\Manager', null, [], '', false); @@ -294,10 +296,6 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getActionFlag') ->will($this->returnValue($actionFlag)); - $this->context - ->expects($this->any()) - ->method('getRedirect') - ->will($this->returnValue($redirect)); $this->context ->expects($this->any()) ->method('getView') @@ -327,10 +325,13 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->never()) ->method('setBeforeWishlistUrl') ->will($this->returnValue(null)); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); $this->createController(); - $this->controller->execute(); + $this->assertSame($this->resultRedirectMock, $this->controller->execute()); } /** @@ -344,7 +345,6 @@ class AddTest extends \PHPUnit_Framework_TestCase ->method('getWishlist') ->will($this->returnValue($wishlist)); - $request = $this->getMock('Magento\Framework\App\Request\Http', ['getParams'], [], '', false); $request ->expects($this->once()) @@ -356,12 +356,10 @@ class AddTest extends \PHPUnit_Framework_TestCase $eventManager = $this->getMock('Magento\Framework\Event\Manager', null, [], '', false); $url = $this->getMock('Magento\Framework\Url', null, [], '', false); $actionFlag = $this->getMock('Magento\Framework\App\ActionFlag', null, [], '', false); - $redirect = $this->getMock('\Magento\Store\App\Response\Redirect', ['redirect'], [], '', false); - $redirect - ->expects($this->once()) - ->method('redirect') - ->with($response, '*/', []) - ->will($this->returnValue(null)); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/', []) + ->willReturnSelf(); $view = $this->getMock('Magento\Framework\App\View', null, [], '', false); $messageManager = $this->getMock('Magento\Framework\Message\Manager', ['addError'], [], '', false); $messageManager @@ -394,10 +392,6 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getActionFlag') ->will($this->returnValue($actionFlag)); - $this->context - ->expects($this->any()) - ->method('getRedirect') - ->will($this->returnValue($redirect)); $this->context ->expects($this->any()) ->method('getView') @@ -406,6 +400,9 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getMessageManager') ->will($this->returnValue($messageManager)); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); $this->customerSession ->expects($this->exactly(1)) @@ -430,7 +427,7 @@ class AddTest extends \PHPUnit_Framework_TestCase $this->createController(); - $this->controller->execute(); + $this->assertSame($this->resultRedirectMock, $this->controller->execute()); } /** @@ -466,12 +463,10 @@ class AddTest extends \PHPUnit_Framework_TestCase $eventManager = $this->getMock('Magento\Framework\Event\Manager', null, [], '', false); $url = $this->getMock('Magento\Framework\Url', null, [], '', false); $actionFlag = $this->getMock('Magento\Framework\App\ActionFlag', null, [], '', false); - $redirect = $this->getMock('\Magento\Store\App\Response\Redirect', ['redirect'], [], '', false); - $redirect - ->expects($this->once()) - ->method('redirect') - ->with($response, '*', ['wishlist_id' => 2]) - ->will($this->returnValue(null)); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*', ['wishlist_id' => 2]) + ->willReturnSelf(); $view = $this->getMock('Magento\Framework\App\View', null, [], '', false); $messageManager = $this->getMock('Magento\Framework\Message\Manager', ['addError'], [], '', false); @@ -505,10 +500,6 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getActionFlag') ->will($this->returnValue($actionFlag)); - $this->context - ->expects($this->any()) - ->method('getRedirect') - ->will($this->returnValue($redirect)); $this->context ->expects($this->any()) ->method('getView') @@ -517,6 +508,9 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getMessageManager') ->will($this->returnValue($messageManager)); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); $this->customerSession ->expects($this->exactly(1)) @@ -559,7 +553,7 @@ class AddTest extends \PHPUnit_Framework_TestCase $this->createController(); - $this->controller->execute(); + $this->assertSame($this->resultRedirectMock, $this->controller->execute()); } /** @@ -683,12 +677,10 @@ class AddTest extends \PHPUnit_Framework_TestCase $url = $this->getMock('Magento\Framework\Url', null, [], '', false); $actionFlag = $this->getMock('Magento\Framework\App\ActionFlag', null, [], '', false); - $redirect = $this->getMock('\Magento\Store\App\Response\Redirect', ['redirect'], [], '', false); - $redirect - ->expects($this->once()) - ->method('redirect') - ->with($response, '*', ['wishlist_id' => 2]) - ->will($this->returnValue(null)); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*', ['wishlist_id' => 2]) + ->willReturnSelf(); $view = $this->getMock('Magento\Framework\App\View', null, [], '', false); @@ -733,10 +725,6 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getActionFlag') ->will($this->returnValue($actionFlag)); - $this->context - ->expects($this->any()) - ->method('getRedirect') - ->will($this->returnValue($redirect)); $this->context ->expects($this->any()) ->method('getView') @@ -745,6 +733,9 @@ class AddTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getMessageManager') ->will($this->returnValue($messageManager)); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); $this->customerSession ->expects($this->exactly(1)) @@ -766,6 +757,6 @@ class AddTest extends \PHPUnit_Framework_TestCase $this->createController(); - $this->controller->execute(); + $this->assertSame($this->resultRedirectMock, $this->controller->execute()); } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php index b99b18f4b87eaa6f95bc93601e434b2ce8bbc417..8d58bf0be7592847c0f13f568d923ff6aeeceba7 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php @@ -3,9 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\Test\Unit\Controller\Index; +use Magento\Framework\Controller\ResultFactory; + class AllcartTest extends \PHPUnit_Framework_TestCase { /** @@ -38,6 +39,21 @@ class AllcartTest extends \PHPUnit_Framework_TestCase */ protected $response; + /** + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultFactoryMock; + + /** + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRedirectMock; + + /** + * @var \Magento\Framework\Controller\Result\Forward|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultForwardMock; + protected function setUp() { $this->context = $this->getMock('Magento\Framework\App\Action\Context', [], [], '', false); @@ -46,6 +62,24 @@ class AllcartTest extends \PHPUnit_Framework_TestCase $this->formKeyValidator = $this->getMock('Magento\Framework\Data\Form\FormKey\Validator', [], [], '', false); $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); $this->response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + $this->resultForwardMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Forward') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactoryMock->expects($this->any()) + ->method('create') + ->willReturnMap( + [ + [ResultFactory::TYPE_REDIRECT, [], $this->resultRedirectMock], + [ResultFactory::TYPE_FORWARD, [], $this->resultForwardMock] + ] + ); } protected function prepareContext() @@ -94,6 +128,9 @@ class AllcartTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getMessageManager') ->will($this->returnValue($messageManager)); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); } public function getController() @@ -114,24 +151,13 @@ class AllcartTest extends \PHPUnit_Framework_TestCase ->method('validate') ->with($this->request) ->will($this->returnValue(false)); - - $this->request - ->expects($this->once()) - ->method('initForward') - ->will($this->returnValue(true)); - $this->request - ->expects($this->once()) - ->method('setActionName') + $this->resultForwardMock->expects($this->once()) + ->method('forward') ->with('noroute') - ->will($this->returnValue(true)); - $this->request - ->expects($this->once()) - ->method('setDispatched') - ->with(false) - ->will($this->returnValue(true)); + ->willReturnSelf(); $controller = $this->getController(); - $controller->execute(); + $this->assertSame($this->resultForwardMock, $controller->execute()); } public function testExecuteWithoutWishlist() @@ -141,63 +167,43 @@ class AllcartTest extends \PHPUnit_Framework_TestCase ->method('validate') ->with($this->request) ->will($this->returnValue(true)); - - $this->request - ->expects($this->once()) - ->method('initForward') - ->will($this->returnValue(true)); - $this->request - ->expects($this->once()) - ->method('setActionName') - ->with('noroute') - ->will($this->returnValue(true)); - $this->request - ->expects($this->once()) - ->method('setDispatched') - ->with(false) - ->will($this->returnValue(true)); - $this->wishlistProvider ->expects($this->once()) ->method('getWishlist') ->will($this->returnValue(null)); + $this->resultForwardMock->expects($this->once()) + ->method('forward') + ->with('noroute') + ->willReturnSelf(); - - $this->getController()->execute(); + $this->assertSame($this->resultForwardMock, $this->getController()->execute()); } public function testExecutePassed() { + $url = 'http://redirect-url.com'; $wishlist = $this->getMock('Magento\Wishlist\Model\Wishlist', [], [], '', false); - $this->formKeyValidator - ->expects($this->once()) + $this->formKeyValidator->expects($this->once()) ->method('validate') ->with($this->request) ->will($this->returnValue(true)); - - $this->request - ->expects($this->once()) + $this->request->expects($this->once()) ->method('getParam') ->with('qty') ->will($this->returnValue(2)); - - $this->response - ->expects($this->once()) - ->method('setRedirect') - ->will($this->returnValue('http://redirect-url.com')); - - $this->wishlistProvider - ->expects($this->once()) + $this->wishlistProvider->expects($this->once()) ->method('getWishlist') ->will($this->returnValue($wishlist)); - - $this->itemCarrier - ->expects($this->once()) + $this->itemCarrier->expects($this->once()) ->method('moveAllToCart') ->with($wishlist, 2) - ->will($this->returnValue('http://redirect-url.com')); + ->willReturn($url); + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') + ->with($url) + ->willReturnSelf(); - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php index fcfec1f1071a82b28b866e753669733d031422de..c2074246b31fa3f197fe5ed5150551f76954526d 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php @@ -3,12 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\Test\Unit\Controller\Index; -use \Magento\Wishlist\Controller\Index\Cart; - +use Magento\Wishlist\Controller\Index\Cart; use Magento\Catalog\Model\Product\Exception as ProductException; +use Magento\Framework\Controller\ResultFactory; /** * @SuppressWarnings(PHPMD.TooManyFields) @@ -71,11 +70,6 @@ class CartTest extends \PHPUnit_Framework_TestCase */ protected $requestMock; - /** - * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $responseMock; - /** * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -102,9 +96,19 @@ class CartTest extends \PHPUnit_Framework_TestCase protected $cartHelperMock; /** - * @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $jsonHelperMock; + protected $resultFactoryMock; + + /** + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRedirectMock; + + /** + * @var \Magento\Framework\Controller\Result\Json|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultJsonMock; /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -152,11 +156,6 @@ class CartTest extends \PHPUnit_Framework_TestCase ->setMethods(['getParams', 'getParam', 'isAjax']) ->getMockForAbstractClass(); - $this->responseMock = $this->getMockBuilder('Magento\Framework\App\ResponseInterface') - ->disableOriginalConstructor() - ->setMethods(['setRedirect', 'representJson']) - ->getMockForAbstractClass(); - $this->redirectMock = $this->getMockBuilder('Magento\Framework\App\Response\RedirectInterface') ->disableOriginalConstructor() ->getMockForAbstractClass(); @@ -174,6 +173,18 @@ class CartTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods(['getUrl']) ->getMockForAbstractClass(); + $this->cartHelperMock = $this->getMockBuilder('Magento\Checkout\Helper\Cart') + ->disableOriginalConstructor() + ->getMock(); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + $this->resultJsonMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); $this->contextMock = $this->getMockBuilder('Magento\Framework\App\Action\Context') ->disableOriginalConstructor() @@ -181,9 +192,6 @@ class CartTest extends \PHPUnit_Framework_TestCase $this->contextMock->expects($this->any()) ->method('getRequest') ->will($this->returnValue($this->requestMock)); - $this->contextMock->expects($this->any()) - ->method('getResponse') - ->will($this->returnValue($this->responseMock)); $this->contextMock->expects($this->any()) ->method('getRedirect') ->will($this->returnValue($this->redirectMock)); @@ -195,15 +203,19 @@ class CartTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($this->messageManagerMock)); $this->contextMock->expects($this->any()) ->method('getUrl') - ->will($this->returnValue($this->urlMock)); - - $this->cartHelperMock = $this->getMockBuilder('Magento\Checkout\Helper\Cart') - ->disableOriginalConstructor() - ->getMock(); + ->willReturn($this->urlMock); + $this->contextMock->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); + $this->resultFactoryMock->expects($this->any()) + ->method('create') + ->willReturnMap( + [ + [ResultFactory::TYPE_REDIRECT, [], $this->resultRedirectMock], + [ResultFactory::TYPE_JSON, [], $this->resultJsonMock] + ] + ); - $this->jsonHelperMock = $this->getMockBuilder('Magento\Framework\Json\Helper\Data') - ->disableOriginalConstructor() - ->getMock(); $this->model = new Cart( $this->contextMock, @@ -215,8 +227,7 @@ class CartTest extends \PHPUnit_Framework_TestCase $this->productHelperMock, $this->escaperMock, $this->helperMock, - $this->cartHelperMock, - $this->jsonHelperMock + $this->cartHelperMock ); } @@ -243,13 +254,12 @@ class CartTest extends \PHPUnit_Framework_TestCase $itemMock->expects($this->once()) ->method('getId') ->willReturn(null); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*', []) + ->willReturnSelf(); - $this->redirectMock->expects($this->once()) - ->method('redirect') - ->with($this->responseMock, '*/*', []) - ->willReturn($this->responseMock); - - $this->assertEquals($this->responseMock, $this->model->execute()); + $this->assertSame($this->resultRedirectMock, $this->model->execute()); } public function testExecuteWithNoWishlist() @@ -285,23 +295,44 @@ class CartTest extends \PHPUnit_Framework_TestCase ->method('getWishlist') ->with($wishlistId) ->willReturn(null); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*', []) + ->willReturnSelf(); - $this->redirectMock->expects($this->once()) - ->method('redirect') - ->with($this->responseMock, '*/*', []) - ->willReturn($this->responseMock); + $this->assertSame($this->resultRedirectMock, $this->model->execute()); + } - $this->assertEquals($this->responseMock, $this->model->execute()); + public function testExecuteWithQuantityArray() + { + $refererUrl = $this->prepareExecuteWithQuantityArray(); + + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') + ->with($refererUrl) + ->willReturnSelf(); + + $this->assertSame($this->resultRedirectMock, $this->model->execute()); + } + + public function testExecuteWithQuantityArrayAjax() + { + $refererUrl = $this->prepareExecuteWithQuantityArray(true); + + $this->resultJsonMock->expects($this->once()) + ->method('setData') + ->with(['backUrl' => $refererUrl]) + ->willReturnSelf(); + + $this->assertSame($this->resultJsonMock, $this->model->execute()); } /** * @param bool $isAjax - * - * @dataProvider dataProviderExecuteWithQuantityArray - * + * @return array * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function testExecuteWithQuantityArray($isAjax) + protected function prepareExecuteWithQuantityArray($isAjax = false) { $itemId = 2; $wishlistId = 1; @@ -505,34 +536,8 @@ class CartTest extends \PHPUnit_Framework_TestCase $this->helperMock->expects($this->once()) ->method('calculate') ->willReturnSelf(); - - $this->jsonHelperMock->expects($this->any()) - ->method('jsonEncode') - ->with(['backUrl' => $refererUrl]) - ->willReturn('{"backUrl":"' . $refererUrl . '"}'); - - $this->responseMock->expects($this->any()) - ->method('setRedirect') - ->with($refererUrl) - ->willReturn($this->responseMock); - $this->responseMock->expects($this->any()) - ->method('representJson') - ->with('{"backUrl":"' . $refererUrl . '"}') - ->willReturnSelf(); - - $expectedResult = ($isAjax ? null : $this->responseMock); - $this->assertEquals($expectedResult, $this->model->execute()); - } - - /** - * @return array - */ - public function dataProviderExecuteWithQuantityArray() - { - return [ - ['isAjax' => false], - ['isAjax' => true], - ]; + + return $refererUrl; } /** @@ -688,12 +693,12 @@ class CartTest extends \PHPUnit_Framework_TestCase ->method('calculate') ->willReturnSelf(); - $this->responseMock->expects($this->once()) - ->method('setRedirect') + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') ->with($indexUrl) - ->willReturn($this->responseMock); + ->willReturnSelf(); - $this->assertEquals($this->responseMock, $this->model->execute()); + $this->assertSame($this->resultRedirectMock, $this->model->execute()); } /** @@ -849,11 +854,11 @@ class CartTest extends \PHPUnit_Framework_TestCase ->method('calculate') ->willReturnSelf(); - $this->responseMock->expects($this->once()) - ->method('setRedirect') + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') ->with($configureUrl) - ->willReturn($this->responseMock); + ->willReturnSelf(); - $this->assertEquals($this->responseMock, $this->model->execute()); + $this->assertSame($this->resultRedirectMock, $this->model->execute()); } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php index 94888effcc121310c5f861654cf5638180e11860..12f3de81f386ccdb5d1fbbf041b254f40bb3d2ba 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php @@ -3,9 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\Test\Unit\Controller\Index; +use Magento\Framework\Controller\ResultFactory; + class IndexTest extends \PHPUnit_Framework_TestCase { /** @@ -29,14 +30,24 @@ class IndexTest extends \PHPUnit_Framework_TestCase protected $wishlistProvider; /** - * @var \Magento\Framework\App\View|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\App\Response\Redirect|\PHPUnit_Framework_MockObject_MockObject */ - protected $view; + protected $redirect; /** - * @var \Magento\Store\App\Response\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $redirect; + protected $resultFactoryMock; + + /** + * @var \Magento\Framework\View\Result\Page|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultPageMock; + + /** + * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutMock; protected function setUp() { @@ -44,8 +55,24 @@ class IndexTest extends \PHPUnit_Framework_TestCase $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); $this->response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false); $this->wishlistProvider = $this->getMock('Magento\Wishlist\Controller\WishlistProvider', [], [], '', false); - $this->view = $this->getMock('Magento\Framework\App\View', [], [], '', false); $this->redirect = $this->getMock('\Magento\Store\App\Response\Redirect', [], [], '', false); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultPageMock = $this->getMockBuilder('Magento\Framework\View\Result\Page') + ->disableOriginalConstructor() + ->getMock(); + $this->layoutMock = $this->getMockBuilder('Magento\Framework\View\Layout') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactoryMock->expects($this->any()) + ->method('create') + ->with(ResultFactory::TYPE_PAGE, []) + ->willReturn($this->resultPageMock); + $this->resultPageMock->expects($this->any()) + ->method('getLayout') + ->willReturn($this->layoutMock); } protected function prepareContext() @@ -84,14 +111,13 @@ class IndexTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getRedirect') ->willReturn($this->redirect); - $this->context - ->expects($this->any()) - ->method('getView') - ->willReturn($this->view); $this->context ->expects($this->any()) ->method('getMessageManager') ->willReturn($messageManager); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); } public function getController() @@ -120,30 +146,10 @@ class IndexTest extends \PHPUnit_Framework_TestCase { $wishlist = $this->getMock('Magento\Wishlist\Model\Wishlist', [], [], '', false); - $layout = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $layout - ->expects($this->once()) - ->method('initMessages') - ->willReturn(true); - - $this->wishlistProvider - ->expects($this->once()) + $this->wishlistProvider->expects($this->once()) ->method('getWishlist') ->willReturn($wishlist); - $this->view - ->expects($this->once()) - ->method('loadLayout') - ->willReturn(true); - $this->view - ->expects($this->once()) - ->method('getLayout') - ->willReturn($layout); - $this->view - ->expects($this->once()) - ->method('renderLayout') - ->willReturn(true); - - $this->getController()->execute(); + $this->assertSame($this->resultPageMock, $this->getController()->execute()); } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php index f2c2954f59d739e122c5e7b2b174136a1731cb9a..96381ac144f7ead0d860646c889ccb1bb30acb20 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php @@ -3,9 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\Test\Unit\Controller\Index; +use Magento\Framework\Controller\ResultFactory; + class RemoveTest extends \PHPUnit_Framework_TestCase { /** @@ -23,16 +24,6 @@ class RemoveTest extends \PHPUnit_Framework_TestCase */ protected $request; - /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject - */ - protected $response; - - /** - * @var \Magento\Framework\App\View|\PHPUnit_Framework_MockObject_MockObject - */ - protected $view; - /** * @var \Magento\Store\App\Response\Redirect|\PHPUnit_Framework_MockObject_MockObject */ @@ -53,17 +44,36 @@ class RemoveTest extends \PHPUnit_Framework_TestCase */ protected $url; + /** + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultFactoryMock; + + /** + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRedirectMock; + protected function setUp() { $this->context = $this->getMock('Magento\Framework\App\Action\Context', [], [], '', false); $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - $this->response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false); $this->wishlistProvider = $this->getMock('Magento\Wishlist\Controller\WishlistProvider', [], [], '', false); - $this->view = $this->getMock('Magento\Framework\App\View', [], [], '', false); $this->redirect = $this->getMock('\Magento\Store\App\Response\Redirect', [], [], '', false); $this->om = $this->getMock('Magento\Framework\App\ObjectManager', [], [], '', false); $this->messageManager = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false); $this->url = $this->getMock('Magento\Framework\Url', [], [], '', false); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactoryMock->expects($this->any()) + ->method('create') + ->with(ResultFactory::TYPE_REDIRECT, []) + ->willReturn($this->resultRedirectMock); } public function tearDown() @@ -71,9 +81,7 @@ class RemoveTest extends \PHPUnit_Framework_TestCase unset( $this->context, $this->request, - $this->response, $this->wishlistProvider, - $this->view, $this->redirect, $this->om, $this->messageManager, @@ -94,10 +102,6 @@ class RemoveTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getRequest') ->willReturn($this->request); - $this->context - ->expects($this->any()) - ->method('getResponse') - ->willReturn($this->response); $this->context ->expects($this->any()) ->method('getEventManager') @@ -114,14 +118,13 @@ class RemoveTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getRedirect') ->willReturn($this->redirect); - $this->context - ->expects($this->any()) - ->method('getView') - ->willReturn($this->view); $this->context ->expects($this->any()) ->method('getMessageManager') ->willReturn($this->messageManager); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); } public function getController() @@ -283,13 +286,12 @@ class RemoveTest extends \PHPUnit_Framework_TestCase ] ); - $this->response - ->expects($this->once()) - ->method('setRedirect') + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') ->with($referer) - ->willReturn(true); + ->willReturnSelf(); - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } public function testExecuteCanNotSaveWishlistAndWithRedirect() @@ -373,19 +375,18 @@ class RemoveTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('getUrl') ->with('*/*') - ->willReturn('http:/test.com/frontname/module/controller/action'); + ->willReturn('http://test.com/frontname/module/controller/action'); $this->redirect ->expects($this->once()) ->method('getRedirectUrl') - ->willReturn('http:/test.com/frontname/module/controller/action'); + ->willReturn('http://test.com/frontname/module/controller/action'); - $this->response - ->expects($this->once()) - ->method('setRedirect') - ->with('http:/test.com/frontname/module/controller/action') - ->willReturn(true); + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') + ->with('http://test.com/frontname/module/controller/action') + ->willReturnSelf(); - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php index 9fddb7383a3034e51fcf973eb797f4638189083a..cb1b05a9328a9203c38aa36d6c9034bfa04b1144 100755 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php @@ -3,9 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\Test\Unit\Controller\Index; +use Magento\Framework\Controller\ResultFactory; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -31,21 +32,6 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase */ protected $request; - /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject - */ - protected $response; - - /** - * @var \Magento\Framework\App\View|\PHPUnit_Framework_MockObject_MockObject - */ - protected $view; - - /** - * @var \Magento\Store\App\Response\Redirect|\PHPUnit_Framework_MockObject_MockObject - */ - protected $redirect; - /** * @var \Magento\Framework\App\ObjectManager|\PHPUnit_Framework_MockObject_MockObject */ @@ -71,6 +57,16 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase */ protected $eventManager; + /** + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultFactoryMock; + + /** + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRedirectMock; + /** * SetUp method * @@ -81,15 +77,23 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase $this->productRepository = $this->getMock('Magento\Catalog\Model\ProductRepository', [], [], '', false); $this->context = $this->getMock('Magento\Framework\App\Action\Context', [], [], '', false); $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - $this->response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false); $this->wishlistProvider = $this->getMock('Magento\Wishlist\Controller\WishlistProvider', [], [], '', false); - $this->view = $this->getMock('Magento\Framework\App\View', [], [], '', false); - $this->redirect = $this->getMock('\Magento\Store\App\Response\Redirect', [], [], '', false); $this->om = $this->getMock('Magento\Framework\App\ObjectManager', [], [], '', false); $this->messageManager = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false); $this->url = $this->getMock('Magento\Framework\Url', [], [], '', false); $this->customerSession = $this->getMock('Magento\Customer\Model\Session', [], [], '', false); $this->eventManager = $this->getMock('Magento\Framework\Event\Manager', [], [], '', false); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactoryMock->expects($this->any()) + ->method('create') + ->with(ResultFactory::TYPE_REDIRECT, []) + ->willReturn($this->resultRedirectMock); } /** @@ -103,10 +107,7 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase $this->productRepository, $this->context, $this->request, - $this->response, $this->wishlistProvider, - $this->view, - $this->redirect, $this->om, $this->messageManager, $this->url, @@ -131,10 +132,6 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getRequest') ->willReturn($this->request); - $this->context - ->expects($this->any()) - ->method('getResponse') - ->willReturn($this->response); $this->context ->expects($this->any()) ->method('getEventManager') @@ -147,18 +144,13 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getActionFlag') ->willReturn($actionFlag); - $this->context - ->expects($this->any()) - ->method('getRedirect') - ->willReturn($this->redirect); - $this->context - ->expects($this->any()) - ->method('getView') - ->willReturn($this->view); $this->context ->expects($this->any()) ->method('getMessageManager') ->willReturn($this->messageManager); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactoryMock); } /** @@ -189,14 +181,12 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase ->method('getParam') ->with('product') ->willReturn(null); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/', []) + ->willReturnSelf(); - $this->redirect - ->expects($this->once()) - ->method('redirect') - ->with($this->response, '*/', []) - ->willReturn(true); - - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } /** @@ -223,14 +213,12 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase ->method('addError') ->with('We can\'t specify a product.') ->willReturn(true); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/', []) + ->willReturnSelf(); - $this->redirect - ->expects($this->once()) - ->method('redirect') - ->with($this->response, '*/', []) - ->willReturn(true); - - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } /** @@ -293,14 +281,12 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase ->method('create') ->with('Magento\Wishlist\Model\Item') ->willReturn($item); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/', []) + ->willReturnSelf(); - $this->redirect - ->expects($this->once()) - ->method('redirect') - ->with($this->response, '*/', []) - ->willReturn(true); - - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } /** @@ -416,14 +402,12 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase ->method('addError') ->with('error-message', null) ->willReturn(true); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*', ['wishlist_id' => 56]) + ->willReturnSelf(); - $this->redirect - ->expects($this->once()) - ->method('redirect') - ->with($this->response, '*/*', ['wishlist_id' => 56]) - ->willReturn(true); - - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } /** * Test execute add success critical exception @@ -556,13 +540,11 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase ->method('addError') ->with('An error occurred while updating wish list.', null) ->willReturn(true); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*', ['wishlist_id' => 56]) + ->willReturnSelf(); - $this->redirect - ->expects($this->once()) - ->method('redirect') - ->with($this->response, '*/*', ['wishlist_id' => 56]) - ->willReturn(true); - - $this->getController()->execute(); + $this->assertSame($this->resultRedirectMock, $this->getController()->execute()); } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php index fbd2ce5f641ac78949c061f63885d182daaad5c9..09ea2bb42c74aacbf7555c36fa41679d86822f43 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php @@ -3,161 +3,148 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\Test\Unit\Controller\Shared; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\Controller\ResultFactory; + class AllcartTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Wishlist\Controller\Shared\Allcart + */ + protected $allcartController; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManagerHelper; + + /** + * @var \Magento\Framework\App\Action\Context + */ + protected $context; + /** * @var \Magento\Wishlist\Controller\Shared\WishlistProvider|\PHPUnit_Framework_MockObject_MockObject */ - protected $wishlistProvider; + protected $wishlistProviderMock; + + /** + * @var \Magento\Wishlist\Model\ItemCarrier|\PHPUnit_Framework_MockObject_MockObject + */ + protected $itemCarrierMock; + + /** + * @var \Magento\Wishlist\Model\Wishlist|\PHPUnit_Framework_MockObject_MockObject + */ + protected $wishlistMock; /** * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */ - protected $request; + protected $requestMock; /** - * @var \Magento\Wishlist\Model\ItemCarrier|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $itemCarrier; + protected $resultFactoryMock; /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject */ - protected $response; + protected $resultRedirectMock; /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Forward|\PHPUnit_Framework_MockObject_MockObject */ - protected $context; + protected $resultForwardMock; protected function setUp() { - $this->wishlistProvider = $this->getMock( - '\Magento\Wishlist\Controller\Shared\WishlistProvider', - [], - [], - '', - false + $this->wishlistProviderMock = $this->getMockBuilder('Magento\Wishlist\Controller\Shared\WishlistProvider') + ->disableOriginalConstructor() + ->getMock(); + $this->itemCarrierMock = $this->getMockBuilder('Magento\Wishlist\Model\ItemCarrier') + ->disableOriginalConstructor() + ->getMock(); + $this->wishlistMock = $this->getMockBuilder('Magento\Wishlist\Model\Wishlist') + ->disableOriginalConstructor() + ->getMock(); + $this->requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http') + ->disableOriginalConstructor() + ->getMock(); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + $this->resultForwardMock = $this->getMockBuilder('Magento\Framework\Controller\Result\Forward') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactoryMock->expects($this->any()) + ->method('create') + ->willReturnMap( + [ + [ResultFactory::TYPE_REDIRECT, [], $this->resultRedirectMock], + [ResultFactory::TYPE_FORWARD, [], $this->resultForwardMock] + ] + ); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->context = $this->objectManagerHelper->getObject( + 'Magento\Framework\App\Action\Context', + [ + 'request' => $this->requestMock, + 'resultFactory' => $this->resultFactoryMock + ] + ); + $this->allcartController = $this->objectManagerHelper->getObject( + 'Magento\Wishlist\Controller\Shared\Allcart', + [ + 'context' => $this->context, + 'wishlistProvider' => $this->wishlistProviderMock, + 'itemCarrier' => $this->itemCarrierMock + ] ); - $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - $this->itemCarrier = $this->getMock('Magento\Wishlist\Model\ItemCarrier', [], [], '', false); - $this->context = $this->getMock('Magento\Framework\App\Action\Context', [], [], '', false); - $this->response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false); } - protected function prepareContext() + public function testExecuteWithWishlist() { - $om = $this->getMock('Magento\Framework\App\ObjectManager', [], [], '', false); - $eventManager = $this->getMock('Magento\Framework\Event\Manager', null, [], '', false); - $url = $this->getMock('Magento\Framework\Url', [], [], '', false); - $actionFlag = $this->getMock('Magento\Framework\App\ActionFlag', [], [], '', false); - $redirect = $this->getMock('\Magento\Store\App\Response\Redirect', [], [], '', false); - $view = $this->getMock('Magento\Framework\App\View', [], [], '', false); - $messageManager = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false); - - $this->context - ->expects($this->any()) - ->method('getObjectManager') - ->will($this->returnValue($om)); - $this->context - ->expects($this->any()) - ->method('getRequest') - ->will($this->returnValue($this->request)); - $this->context - ->expects($this->any()) - ->method('getResponse') - ->will($this->returnValue($this->response)); - $this->context - ->expects($this->any()) - ->method('getEventManager') - ->will($this->returnValue($eventManager)); - $this->context - ->expects($this->any()) - ->method('getUrl') - ->will($this->returnValue($url)); - $this->context - ->expects($this->any()) - ->method('getActionFlag') - ->will($this->returnValue($actionFlag)); - $this->context - ->expects($this->any()) - ->method('getRedirect') - ->will($this->returnValue($redirect)); - $this->context - ->expects($this->any()) - ->method('getView') - ->will($this->returnValue($view)); - $this->context - ->expects($this->any()) - ->method('getMessageManager') - ->will($this->returnValue($messageManager)); - } + $url = 'http://redirect-url.com'; + $quantity = 2; - public function getController() - { - $this->prepareContext(); - return new \Magento\Wishlist\Controller\Shared\Allcart( - $this->context, - $this->wishlistProvider, - $this->itemCarrier - ); + $this->wishlistProviderMock->expects($this->once()) + ->method('getWishlist') + ->willReturn($this->wishlistMock); + $this->requestMock->expects($this->any()) + ->method('getParam') + ->with('qty') + ->willReturn($quantity); + $this->itemCarrierMock->expects($this->once()) + ->method('moveAllToCart') + ->with($this->wishlistMock, 2) + ->willReturn($url); + $this->resultRedirectMock->expects($this->once()) + ->method('setUrl') + ->with($url) + ->willReturnSelf(); + + $this->assertSame($this->resultRedirectMock, $this->allcartController->execute()); } public function testExecuteWithNoWishlist() { - $this->wishlistProvider->expects($this->once()) + $this->wishlistProviderMock->expects($this->once()) ->method('getWishlist') ->willReturn(false); - - $this->request - ->expects($this->once()) - ->method('initForward') - ->will($this->returnValue(true)); - $this->request - ->expects($this->once()) - ->method('setActionName') + $this->resultForwardMock->expects($this->once()) + ->method('forward') ->with('noroute') - ->will($this->returnValue(true)); - $this->request - ->expects($this->once()) - ->method('setDispatched') - ->with(false) - ->will($this->returnValue(true)); - - $controller = $this->getController(); - $controller->execute(); - } - - public function testExecuteWithWishlist() - { - $wishlist = $this->getMockBuilder('Magento\Wishlist\Model\Wishlist') - ->disableOriginalConstructor() - ->getMock(); - $this->wishlistProvider->expects($this->once()) - ->method('getWishlist') - ->willReturn($wishlist); - - $this->request - ->expects($this->once()) - ->method('getParam') - ->with('qty') - ->will($this->returnValue(2)); - - $this->itemCarrier - ->expects($this->once()) - ->method('moveAllToCart') - ->with($wishlist, 2) - ->will($this->returnValue('http://redirect-url.com')); - - $this->response - ->expects($this->once()) - ->method('setRedirect') - ->will($this->returnValue('http://redirect-url.com')); + ->willReturnSelf(); - $controller = $this->getController(); - $controller->execute(); + $this->assertSame($this->resultForwardMock, $this->allcartController->execute()); } } diff --git a/app/code/Magento/Wishlist/composer.json b/app/code/Magento/Wishlist/composer.json index 59eee0b1b1feb0c7ab6eccbe0a4563a729e34340..b5400d7ffae45854dde81421038bcb58547818b7 100644 --- a/app/code/Magento/Wishlist/composer.json +++ b/app/code/Magento/Wishlist/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta6", - "magento/module-customer": "0.74.0-beta6", - "magento/module-catalog": "0.74.0-beta6", - "magento/module-checkout": "0.74.0-beta6", - "magento/module-theme": "0.74.0-beta6", - "magento/module-catalog-inventory": "0.74.0-beta6", - "magento/module-rss": "0.74.0-beta6", - "magento/module-backend": "0.74.0-beta6", - "magento/module-sales": "0.74.0-beta6", - "magento/module-grouped-product": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", - "magento/module-ui": "0.74.0-beta6", + "magento/module-store": "0.74.0-beta7", + "magento/module-customer": "0.74.0-beta7", + "magento/module-catalog": "0.74.0-beta7", + "magento/module-checkout": "0.74.0-beta7", + "magento/module-theme": "0.74.0-beta7", + "magento/module-catalog-inventory": "0.74.0-beta7", + "magento/module-rss": "0.74.0-beta7", + "magento/module-backend": "0.74.0-beta7", + "magento/module-sales": "0.74.0-beta7", + "magento/module-grouped-product": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", + "magento/module-ui": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-configurable-product": "0.74.0-beta6", - "magento/module-downloadable": "0.74.0-beta6", - "magento/module-bundle": "0.74.0-beta6", - "magento/module-cookie": "0.74.0-beta6" + "magento/module-configurable-product": "0.74.0-beta7", + "magento/module-downloadable": "0.74.0-beta7", + "magento/module-bundle": "0.74.0-beta7", + "magento/module-cookie": "0.74.0-beta7" }, "type": "magento2-module", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Wishlist/view/adminhtml/layout/customer_form.xml b/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_edit.xml similarity index 90% rename from app/code/Magento/Wishlist/view/adminhtml/layout/customer_form.xml rename to app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_edit.xml index 778b395ef14f8086c8c826715669fc6e6d6b03f4..c2caa32651b3797fb91742ea16f9dc1e57eda4dc 100644 --- a/app/code/Magento/Wishlist/view/adminhtml/layout/customer_form.xml +++ b/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_edit.xml @@ -7,7 +7,7 @@ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> - <referenceBlock name="form"> + <referenceBlock name="customer_form"> <block class="Magento\Wishlist\Block\Adminhtml\WishlistTab" name="wishlist" /> </referenceBlock> </body> diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_footer.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_footer.less index c8333911914ef0b9074034bd5f189d17d516fe12..290056b3664b9ec988dec9870b94a528d4a54edc 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_footer.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_footer.less @@ -38,6 +38,10 @@ @_link-text-decoration-active: false ); } + .admin__control-select { + max-width: 52rem; + width: 100%; + } } .magento-version { diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less index 0101fe2439257f2c88766365f6bdf0b407fd8c46..2fe7569f06c995e426241930d01694c5fa15c438 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less @@ -73,16 +73,18 @@ position: relative; text-align: center; z-index: @menu__z-index; - &:focus { - background-color: @menu-item__active__background-color; - box-shadow: none; - + .admin__menu { - .level-0 { - &:first-child { - > a { - background-color: @menu__background-color; - &:after { - display: none; + ._keyfocus & { + &:focus { + background-color: @menu-item__active__background-color; + box-shadow: none; + + .admin__menu { + .level-0 { + &:first-child { + > a { + background-color: @menu__background-color; + &:after { + display: none; + } } } } @@ -275,25 +277,16 @@ margin: -(@submenu-heading-group__indent-bottom) @submenu__padding-horizontal * 2 + @submenu-action-close__indent-right 3.8rem @submenu__padding-horizontal * 2; } - .submenu-close { - &:extend(.abs-action-reset all); + .action-close { padding: 2.4rem @submenu-action-close__indent-right; position: absolute; right: 0; top: 0; - &:active { - .scale(); - } &:before { - &:extend(.abs-icon all); color: @submenu-section-label__color; - content: @icon-close-mage__content; font-size: 1.7rem; - .transition(color); } &:hover { - cursor: pointer; - text-decoration: none; &:before { color: @color-white; } diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/_actions-group.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/_actions-group.less index c7c4a1d35bd596fe0f363e763fd50d2d006e5bcf..716248651a8add1391f46575e8323e20a1d7dbd9 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/_actions-group.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/_actions-group.less @@ -19,53 +19,7 @@ // Variables // --------------------------------------------- -@page-header-action__height: 3.4rem; -@page-header-action__color: @text__color; -@page-header-action__hover__color: darken(@page-header-action__color, 20%); -@page-header-action__background-color: @page-wrapper__background-color; -@page-header-action__active__border-color: @color-blue-pure; -@page-header-action__border-color: @color-light-gray; - -// -// Extends -// --------------------------------------------- - -.abs-page-header-action { - background-color: @page-header-action__background-color; - border: 1px solid transparent; - border-bottom: none; - color: @page-header-action__color; - display: inline-block; - height: @page-header-action__height; - position: relative; - transition: border-color @appering__transition-duration @apperaing__transition-timing-function; - &:hover { - color: @page-header-action__hover__color; - text-decoration: none; - } -} - -.abs-page-header-action-menu { - background-color: @page-header-action__background-color; - border: 1px solid @page-header-action__active__border-color; - box-shadow: @component__box-shadow__base; - margin-top: -1px; - opacity: 0; - position: absolute; - right: 0; - top: 100%; - transition: all @appering__transition-duration @apperaing__transition-timing-function; - visibility: hidden; - &:before { - content: ''; - position: absolute; - } - > li { - display: block; - > a { - } - } -} +@page-header-action__height: @action__height + .1rem; // diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_notifications.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_notifications.less index fd094d1ee44c7d1516e6f1989fb7086ad5b5034b..8d88b1044fc973c63d5f191a9073b77a862de7f6 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_notifications.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_notifications.less @@ -18,14 +18,14 @@ @notifications-action__padding-bottom: (@page-header-action__height - @notifications-action-icon__size) / 2 - .05rem; @notifications-action__padding-side: 2rem; @notifications-action__padding-top: (@page-header-action__height - @notifications-action-icon__size) / 2 + .05rem; -@notifications-action__hover__color: darken(@page-header-action__color, 20%); +@notifications-action__hover__color: darken(@action-dropdown__color, 20%); @notifications-action-icon__size: 1.9rem; @notifications-action-menu__z-index: @header__z-index; @notifications-close__color: @color-gray80; @notifications-counter__background-color: @color-tomato-brick; @notifications-entry__padding-top: .6rem; -@notifications-entry__hover__background-color: @color-blue-clear-sky; +@notifications-entry__hover__background-color: @action__hover__background-color; @notifications-list__width: 32rem; @notifications-title__color: @color-light-phoenix; @notifications-time__color: @color-very-dark-gray1; @@ -39,33 +39,41 @@ &.active { z-index: @notifications-action-menu__z-index; // Should be over global search when active .notifications-action { - border-color: @page-header-action__active__border-color; + border-color: @action-dropdown__active__border-color; box-shadow: @component__box-shadow__base; &:after { - background-color: @page-header-action__background-color; + border: none; + background-color: @action-dropdown__background-color; content: ''; + display: block; height: @component__shadow-size__base + 1; left: -(@component__shadow-size__base + 1); + margin-top: 0; position: absolute; right: 0; top: 100%; + width: auto; } } - .notifications-list { - opacity: 1; - visibility: visible; - } + } + // Notifications dropdown + .admin__action-dropdown-menu { + padding: 1rem 0 0; + width: @notifications-list__width; } } .notifications-action { - &:extend(.abs-page-header-action all); + height: @page-header-action__height; padding: @notifications-action__padding-top @notifications-action__padding-side @notifications-action__padding-bottom; - z-index: 2; + &:after { + display: none; + } &:before { &:extend(.abs-icon all); content: @icon-notification-02__content; font-size: @notifications-action-icon__size; + margin-right: 0; } &:active { &:before { @@ -89,21 +97,11 @@ } } -.notifications-list { - &:extend(.abs-page-header-action-menu all); - padding-top: 1rem; - width: @notifications-list__width; - z-index: 1; - &:before { - z-index: 2; - } -} - .notifications-entry { line-height: @line-height__base; padding: @notifications-entry__padding-top @notifications-action__padding-side .8rem; position: relative; - transition: background-color .2s linear; + transition: @smooth__background-color; &:hover { background-color: @notifications-entry__hover__background-color; } diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_search.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_search.less index 8b733d549c46afbd5e8f133acc3ec51ee86b5515..27524d7d4d0854693596871cd21c5d8f05dd84b8 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_search.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_search.less @@ -43,8 +43,8 @@ min-width: @search-global-field__width; &._active { .search-global-input { - background-color: @page-header-action__background-color; - border-color: @page-header-action__active__border-color; + background-color: @action-dropdown__background-color; + border-color: @action-dropdown__active__border-color; box-shadow: @component__box-shadow__base; padding-right: @search-global-input__active__padding-right; width: @search-global-input__active__width; @@ -70,7 +70,7 @@ width: @search-global-input__active__width; } .search-global-menu { - border: 1px solid @page-header-action__active__border-color; + border: 1px solid @action-dropdown__active__border-color; border-top-color: transparent; box-shadow: @component__box-shadow__base; left: 0; @@ -81,7 +81,7 @@ top: 100%; z-index: 2; &:after { - background-color: @page-header-action__background-color; + background-color: @action-dropdown__background-color; content: ''; height: @component__shadow-size__base; left: 0; @@ -90,8 +90,8 @@ top: -@component__shadow-size__base; } > li { - background-color: @page-header-action__background-color; - border-top: 1px solid @page-header-action__border-color; + background-color: @action-dropdown__background-color; + border-top: 1px solid @action-dropdown__border-color; display: block; font-size: @font-size__s; padding: @search-global-input__padding-top @search-global-input__padding-side @search-global-input__padding-bottom; @@ -120,7 +120,7 @@ } &:hover { &:before { - color: @page-header-action__hover__color; + color: @action-dropdown__hover__color; } } &:before { diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_user.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_user.less index 678ed4b2342689e39c6a8bc2e1e8b21288409102..e43ef98b27b22da4156f8e2427c6eab0bbd2ae4c 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_user.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/header/actions-group/_user.less @@ -11,8 +11,6 @@ // Variables // --------------------------------------------- -@user__font-size: round(@font-size__base - .1rem, 1); - @user-account__padding-bottom: .4rem; @user-account__padding-left: 4rem; @user-account__padding-top: .7rem; @@ -20,6 +18,8 @@ @user-account-menu__min-width: 20rem; @user-account-menu__z-index: @notifications-action-menu__z-index - 10; // Should be lower than notifications +@user-account-menu__hover__background-color: @action__hover__background-color; +@user-account-menu__active__background-color: darken(@color-blue-clear-sky, 5%); // @@ -27,102 +27,74 @@ float: right; line-height: @line-height__base; // ToDo UI: Delete with admin scope margin-left: .3rem; - position: relative; z-index: @user-account-menu__z-index; + &._active, &.active { - .admin-user-account { - border-color: @page-header-action__active__border-color; + // User account action + .admin__action-dropdown { + border-color: @action-dropdown__active__border-color; box-shadow: @component__box-shadow__base; } - .admin-user-account-text-wrapper { - &:after { - background-color: @page-header-action__background-color; - content: ''; - height: @component__shadow-size__base + 1; - left: -(@component__shadow-size__base + 1); - position: absolute; - right: 0; - top: 100%; + } + // User account action + .admin__action-dropdown { + .action-toggle-triangle( + @_dropdown__padding-right: @user-account__padding-right; + @_triangle__color: @action-dropdown__color; + @_triangle__hover__color: @action-dropdown__hover__color; + @_triangle__right: 1.3rem; + ); + height: @page-header-action__height; + padding-bottom: @user-account__padding-bottom; + padding-left: @user-account__padding-left; + padding-top: @user-account__padding-top; + &:before { + @_icon-user__size: 2rem; + + &:extend(.abs-icon all); + content: @icon-account__content; + font-size: @_icon-user__size; + left: 1.1rem; + margin-top: -(@_icon-user__size / 2) - .1rem; + position: absolute; + top: 50%; + } + } + // User account menu + .admin__action-dropdown-menu { + @_user-menu__indent-side: 1rem; + min-width: @user-account-menu__min-width; + padding-left: @_user-menu__indent-side; + padding-right: @_user-menu__indent-side; + > li { + > a { + padding-right: (@user-account__padding-right - @_user-menu__indent-side); + padding-left: .5em; + white-space: nowrap; + transition: @smooth__background-color; + &:hover { + background-color: @user-account-menu__hover__background-color; + color: @action-dropdown__color; + } + &:active { + background-color: @user-account-menu__active__background-color; + bottom: -1px; + position: relative; + } } } - .admin-user-menu { - opacity: 1; - visibility: visible; + .admin-user-name { + .text-overflow-ellipsis(); + display: inline-block; + max-width: @user-account-menu__min-width; + overflow: hidden; + vertical-align: top; } } } -.admin-user-account { - &:extend(.abs-page-header-action all); - .dropdown-triangle( - @_dropdown__padding-right: @user-account__padding-right; - @_triangle__color: @page-header-action__color; - @_triangle__hover__color: @page-header-action__hover__color; - @_triangle__right: 1.3rem; - ); - font-size: @user__font-size; - letter-spacing: .05em; - padding-bottom: @user-account__padding-bottom; - padding-left: @user-account__padding-left; - padding-top: @user-account__padding-top; - z-index: 2; - &:before { - @_icon-user__size: 2rem; - - &:extend(.abs-icon all); - content: @icon-account__content; - font-size: @_icon-user__size; - left: 1.1rem; - margin-top: -(@_icon-user__size / 2) - .1rem; - position: absolute; - top: 50%; - } -} - .admin-user-account-text { + .text-overflow-ellipsis(); display: inline-block; max-width: @user-account-menu__min-width - @user-account__padding-left - @user-account__padding-right - 2rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.admin-user-menu { - @_user-menu__inden-side: 1rem; - - &:extend(.abs-page-header-action-menu all); - line-height: @line-height__base; - min-width: @user-account-menu__min-width; - padding: .5em @_user-menu__inden-side; - z-index: 1; - &:before { - z-index: 1; - } - > li { - > a { - color: @page-header-action__color; - display: block; - padding: .6rem (@user-account__padding-right - @_user-menu__inden-side) .6rem .5em; - text-decoration: none; - transition: background-color .1s linear; - white-space: nowrap; - &:hover { - background-color: @dropdown-menu__hover__background-color; - color: @page-header-action__color; - } - &:active { - background-color: @dropdown-menu__active__background-color; - bottom: -1px; - position: relative; - } - } - } - .admin-user-name { - display: inline-block; - max-width: @user-account-menu__min-width; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: text-top; - white-space: nowrap; - } } diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less index 8fc37b9a87900f1e8bfb4187f9c6573cb30fd66b..1e410484253ff275204b387310b92fe406181c64 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less @@ -12,7 +12,7 @@ // Components // --------------------------------------------- -@import 'actions_bar/_store-switcher.less'; +@import 'actions-bar/_store-switcher.less'; // // Variables @@ -34,7 +34,7 @@ } .page-main-actions { - margin: 0 0 2rem; + margin: 0 0 @indent__l; } // @@ -52,15 +52,13 @@ z-index: @page-actions__fixed__z-index; .page-actions-inner { &:before { + .text-overflow-ellipsis(); color: @page-title__color; content: attr(data-title); float: left; font-size: @page-title__font-size; margin-top: .3rem; max-width: 50%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; } } } @@ -105,6 +103,7 @@ } } .actions-split { + &:extend(.abs-actions-split-xl all); float: right; margin-left: @_page-action__indent; .vendor-prefix-order(2); diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_page-nav.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_page-nav.less index 09319136bec92e3efe47253d810c21eba1eacd4b..0071951108a8b8bd2be488be74e487b25762675d 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_page-nav.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_page-nav.less @@ -23,7 +23,7 @@ @admin__page-nav-item__hover__background-color: darken(@admin__page-nav__background-color, 5%); @admin__page-nav-link__color: @color-very-dark-gray-black; -@admin__page-nav-link__padding: @indent__base 4rem @indent__base 1rem; +@admin__page-nav-link__padding: @indent__base 4rem @indent__base @indent__s; @admin__page-nav-link__hover__color: @color-very-dark-gray-black; @admin__page-nav-link__changed__color: @color-very-dark-gray; @@ -133,7 +133,7 @@ .admin__page-nav-items { list-style-type: none; margin: 0; - padding: 0; + padding: @indent__s 0 @admin__page-nav-item__margin-vertical 0; } .admin__page-nav-item { @@ -180,10 +180,6 @@ display: inline-block; } } - - &:last-child { - margin-bottom: @admin__page-nav-item__margin-vertical; - } } @@ -276,7 +272,7 @@ box-shadow: @admin__page-nav-tooltip__box-shadow; display: none; font-weight: @font-weight__regular; - left: -1rem; + left: -@indent__s; line-height: @line-height__base; padding: 2rem; position: absolute; diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/actions_bar/_store-switcher.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/actions-bar/_store-switcher.less similarity index 98% rename from app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/actions_bar/_store-switcher.less rename to app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/actions-bar/_store-switcher.less index 3e699e2172984de88021448463571bcd9f5f87e1..99527ea22ca0b8ea743dc380f30360a5e6f02dd3 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/actions_bar/_store-switcher.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/actions-bar/_store-switcher.less @@ -13,9 +13,10 @@ color: @text__color; // ToDo UI: Delete with admin scope float: left; font-size: round(@font-size__base - .1rem, 1); - margin-top: 1.1rem; + margin-top: .7rem; .admin__action-dropdown { margin-left: .5em; + background-color: @page-main-actions__background-color; } .dropdown { .dropdown( diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less index 8155f8e461eabf82cc8007f13c086edcbf402ebf..bb55d0e0722cdbb18b1b315f8ce82703ebeea40c 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less @@ -27,7 +27,7 @@ padding-left: 0; } } - &.table-info { + &.admin__table-primary { th { border-top: 0; } @@ -91,6 +91,9 @@ background: @dashboard-tabs__background-color; font-size: @dashboard__font-size__base; } + .ui-tabs-panel { + border-top: 1px solid @color-gray68; + } } // diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less index 7ba168e1ab2333553e3416ff40e09f404872faac..bf9bfec974326847996124b11b68fa4867defb75 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less @@ -18,12 +18,12 @@ // Admin user auth pages layout // --------------------------------------------- -// Header +// Header .login-header { margin: 0 0 3rem; } -// Login box +// Login box .page-layout-admin-login { align-items: center; .vendor-prefix-display(flex); @@ -38,6 +38,7 @@ margin: auto; max-width: @login-box__max-width; min-height: @login-box__min-height; + min-width: 0; padding: 40px 80px 50px; position: relative; width: 100%; diff --git a/app/design/adminhtml/Magento/backend/Magento_Downloadable/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Downloadable/web/css/source/_module.less index af531ff02ac2067b0fc1d51bab40c460070df5a3..3411169b6c0028f8e28a2493f6d1ee1f07b13de0 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Downloadable/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Downloadable/web/css/source/_module.less @@ -59,19 +59,6 @@ } } - .action-remove { - .button-reset(); - .icon-font( - @icon-delete__content, - @icons-admin__font-name, - @_icon-font-size: 1.8rem, - @_icon-font-line-height: 16px, - @_icon-font-text-hide: true, - @_icon-font-position: after, - @_icon-font-color: @color-brown-darkie - ); - margin-top: .5rem; - } } @-moz-document url-prefix() { // Firefox fieldset overflow bug fix diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/_module.less index 910cec4be04dfc70580ab6632d24ba2627acb519..b27606f18db19606eebfad18a29e4792deee9b15 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/_module.less @@ -3,10 +3,5 @@ // * See COPYING.txt for license details. // */ -// -// Pages -// _____________________________________________ - -@import 'module/_order-create.less'; -@import 'module/_order-create-sidebar.less'; -@import 'module/_order-create-table.less'; +@import 'module/_order.less'; +@import 'module/_edit-order.less'; diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_edit-order.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_edit-order.less new file mode 100644 index 0000000000000000000000000000000000000000..860f0f37660ee8ba416d59dd615c7ed5489561dd --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_edit-order.less @@ -0,0 +1,91 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// --------------------------------------------- + +@edit-order-comment-notes__border-color: @color-gray65; +@edit-order-comment-notes__font-size: @font-size__s; + +// +// Table secondary for edit order +// --------------------------------------------- + +.abs-admin__table-secondary-edit-order { + th { + font-weight: @font-weight__regular; + text-align: left; + vertical-align: top; + } + td { + text-align: right; + } + tr { + &:last-child { + td { + border: none; + } + } + } +} + +// +// Order information +// --------------------------------------------- + +.order-information-table { + &:extend(.abs-admin__table-secondary-edit-order all); +} + +// +// Order account information +// --------------------------------------------- + +.order-account-information-table { + &:extend(.abs-admin__table-secondary-edit-order all); +} + +// +// Edit order tables +// --------------------------------------------- + +.edit-order-table { + &:extend(.abs-order-tables all); + &:extend(.abs-order-tbody-border all); + margin-bottom: 5rem; + tfoot { + &._hide { + display: none; + } + td { + padding-top: @order-create-sidebar__margin__m; + } + .col-total { + text-align: right; + } + } + .edit-total-price-block { + padding-left: 3rem; + } +} + +.order-subtotal-table { + tr { + td { + &:last-child { + text-align: right; + } + } + } +} + +.order-history-block { + margin: 0 0 5rem; +} + +.order-history-comments-actions { + margin-top: @order-create-sidebar__margin__reqular; +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create-table.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create-table.less deleted file mode 100644 index a9594b130c1e82a0256b9a09f12e11ada61dfca9..0000000000000000000000000000000000000000 --- a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create-table.less +++ /dev/null @@ -1,174 +0,0 @@ -// /** -// * Copyright © 2015 Magento. All rights reserved. -// * See COPYING.txt for license details. -// */ - -// -// Variables -// --------------------------------------------- - -@order-create-table__border-color: @table-td__border-color; -@order-create-sku__background: @admin__page-nav__background-color; -@order-create-sku__padding: @indent__base; -@order-create-sku-table__border-color: @color-white; - -// - -// -// Table -// --------------------------------------------- - -.order-tables { - margin: 0 0 @order-create-sidebar__margin-reqular; - width: 100%; - th { - border-top: 0; - font-size: 1.3rem; - } - td { - border-bottom: none; - padding-top: @order-create-sidebar__padding; - } - tbody { - tr { - &:last-child { - td { - border-bottom: 1px solid @order-create-table__border-color; - } - } - &.border { - td { - padding-top: 0; - } - } - } - } - .col-qty { - .admin__control-text { - &:extend(.abs-control-qty all); - } - } - .col-actions { - .admin__control-select { - width: 13rem; - } - } - .price { - display: inline-block; - margin: 0 0 @order-create-sidebar__margin-small; - } - .custom-price-block { - font-size: @order-create-sidebar__font-size-xs; - margin: 0 0 @order-create-sidebar__margin-small; - + .admin__control-text { - &:extend(.abs-control-price); - } - } - .discount-price-block { - font-size: @order-create-sidebar__font-size-xs; - } - .product-configure-block { - margin: 1rem 0 0; - .disabled { - display: none; - } - } -} - -.order-search-items { - .grid { - .action-configure { - float: right; - } - .col-id, - .col-price, - .col-in_products { - width: 10rem; - } - } -} - -// -// Add by SKU -// --------------------------------------------- - -.add-by-sku-wrapper { - .add-by-sku { - background: @order-create-sku__background; - clear: both; - margin: 0 0 @indent__base; - padding: @order-create-sku__padding; - } - .table-info { - color: @order-create-sidebar__color; - } - .admin__field-note { - margin: 1.4rem 0; - } - .table-info { - th { - border-top: none; - } - th, - td { - border-bottom-color: @order-create-sku-table__border-color; - &:first-child { - padding-left: 0; - } - } - } - .action-reset, - .action-delete { - &:extend(.abs-action-reset all); - &:extend(.abs-icon all); - display: inline-block; - font-size: @order-create-sidebar__font-size + 0.1rem; - margin-left: 1.2rem; - padding-top: @order-create-sidebar__margin-small + 0.2rem; - vertical-align: middle; - &:after { - color: @order-create-sidebar__color; - content: @order-create-icon-remove__content; - } - &:hover { - &:after { - color: @order-create-icon-plus__hover__color; - } - } - > span { - &:extend(.abs-visually-hidden all); - } - } - .action-reset { - margin-top: -.4rem; - opacity: .5; - padding-top: 0; - &:after { - content: @order-create-icon-reset__content; - } - &:hover { - opacity: 1; - } - } - .col-qty { - .admin__control-text { - &:extend(.abs-control-qty all); - } - } -} - -// -// Product configure popup -// --------------------------------------------- - -.product-configure-popup { - .weee { - .price-wrapper { - display: block; - font-size: 1.3rem; - &:before { - content: attr(data-label) ": "; - } - } - } -} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create.less deleted file mode 100644 index 5ff4e9228ffd85bce65c88fbb894378729b318db..0000000000000000000000000000000000000000 --- a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create.less +++ /dev/null @@ -1,416 +0,0 @@ -// /** -// * Copyright © 2015 Magento. All rights reserved. -// * See COPYING.txt for license details. -// */ - -// -// Variables -// --------------------------------------------- - -@order-create-icon-refresh__font-size: 2rem; -@order-create-icon-refresh__color: @color-gray83; -@order-create-icon-refresh__hover__color: darken(@color-gray83, 10%); - -@order-create-icon-add__content: @icon-arrow-right__content; -@order-create-icon-configure__content: @icon-systems__content; -@order-create-icon-remove__content: @icon-delete__content; -@order-create-icon-reset__content: @icon-remove-small__content; -@order-create-icon-refresh__content: @icon-refresh__content; -@order-create-icon-plus__content: @icon-plus__content; -@order-create-icon-plus__hover__color: @color-very-dark-gray-black2; - -// - -// -// Layout -// --------------------------------------------- - -.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { - .order-details { - float: right; - #mix-grid .width(9,12); - margin-left: 0; - } - .order-sidebar { - #mix-grid .column(3,12); - margin-left: 0; - } - - .order-billing-address, - .order-billing-method, - .order-history { - float: left; - #mix-grid .width(6,12); - } - - .order-shipping-address, - .order-shipping-method, - .order-totals { - float: right; - #mix-grid .width(6,12); - } -} - -// -// Select Store Scope -// --------------------------------------------- - -.tree-store-scope { - max-width: 50rem; - - .admin__field { - margin: 0 0 1rem; - } -} - -// -// Order discounts -// --------------------------------------------- - -.order-discounts { - &:extend(.abs-clearfix all); - margin-top: @indent__base; - .action-secondary { - float: right; - margin-top: 2.1rem; - } - .order-coupons { - float: left; - } - .admin__field { - display: inline-block; - margin: 0 3.5rem 0 0; - vertical-align: top; - - .admin__field-control { - padding-right: 32px; - position: relative; - } - - .action-default { - &:extend(.abs-action-reset all); - top: 7px; - position: absolute; - right: 0; - > span { - .extend__visually-hidden(); - } - - &:before { - &:extend(.abs-icon all); - content: @order-create-icon-add__content; - } - - &:hover { - color: @order-create-icon-plus__hover__color; - } - } - p { - margin: @indent__s 0 0; - } - } - .action-remove { - color: @color-brownie; - margin-left: @indent__xs; - &:hover { - color: @order-create-icon-plus__hover__color; - text-decoration: none; - } - > span { - .extend__visually-hidden(); - } - &:before { - &:extend(.abs-icon all); - content: @order-create-icon-remove__content; - } - } -} - -// -// Order Account Information -// --------------------------------------------- - -.order-account-information { - .admin__fieldset { - &:extend(.abs-clearfix all); - } - .admin__field { - margin-bottom: 0; - } - .field-group_id { - float: left; - } - .field-email { - margin-top: 0; - overflow: hidden; - } -} - -// -// Order Address Information -// --------------------------------------------- - -.order-details { - .order-search-items { - .col-qty { - .admin__control-text { - &:extend(.abs-control-qty); - } - } - } - - .admin__fieldset-wrapper:not(:last-child) { - margin-bottom: 5rem; - } - - .admin__fieldset-wrapper-content { - &:extend(.abs-clearfix all); - } - - .admin__fieldset-wrapper-title { - &:extend(.abs-clearfix all); - border-bottom: 1px solid @color-gray80; - margin-bottom: @order-create-sidebar__margin-reqular; - padding-bottom: @indent__xs; - .actions { - float: right; - margin-bottom: @order-create-sidebar__margin-reqular; - margin-top: -@indent__xs; - } - .action-secondary { - margin-left: @indent__base; - } - .title { - margin: 0; - } - } - - .admin__legend { - &:extend(.abs-fieldset-legend all); - } - - .admin__field { - &:extend(.abs-field-rows all); - } - - .admin__field-option { - .admin__field-label { - display: block; - width: auto; - } - } -} - -.field-vat-number { - .action-default { - &:extend(.action-tertiary all); - font-weight: @font-weight__regular; - margin-top: @indent__s; - padding: 0; - } -} - -// -// Order Payment & Shipping Information -// --------------------------------------------- - -.order-methods { - .admin__field { - &:extend(.abs-field-rows all); - } - .admin__fieldset-wrapper-content { - .admin__fieldset-wrapper-title { - &:extend(.abs-fieldset-legend all); - border-bottom: 0; - margin-bottom: 1.5rem; - padding: 0; - strong { - font-weight: @font-weight__semibold; - } - } - } -} - -.admin__payment-method-wapper { - margin: 0; - .admin__fieldset { - padding: 1.5rem 0 @indent__base @field-control-option-label__padding-left; - } - .admin__field { - &:last-child { - margin-bottom: 0; - } - } -} - -.admin__order-shipment-methods-title { - font-weight: @font-weight__bold; - margin: 0 0 @indent__xs; -} - -.admin__order-shipment-methods-options { - margin: 0 0 @indent__base; -} - -.admin__order-shipment-methods-options-list { - list-style: none; - margin: 0; -} - -.order-shipping-method-summary { - padding-top: @field-option__padding-top; -} - -.order-shipping-method, -.order-billing-method { - position: relative; -} - -.order-shipping-method-summary, -.order-shipping-method { - .action-default { - &:extend(.action-tertiary all); - font-weight: @font-weight__regular; - padding: 0; - } -} - -.order-methods-overlay { - background: rgba(255, 255, 255, .5); - bottom: 0; - left: 0; - position: absolute; - right: 0; - top: 0; - span { - background: @color-white; - display: block; - font-weight: @font-weight__bold; - left: 0; - position: absolute; - top: 48px; - } - .order-shipping-address & { - span { - top: 27px; - } - } -} - -// -// Order Errors -// --------------------------------------------- - -.order-errors { - .col-qty { - .admin__control-text { - &:extend(.abs-control-qty all); - } - } -} - -// -// Gift options -// --------------------------------------------- - -.order-gift-options { - &:extend(.abs-clearfix all); - .card-price-box { - display: none; - &._active { - display: block; - } - } - - .price-box { - .price { - font-weight: @font-weight__bold; - } - } - - > .giftmessage-order-create { - float: left; - #mix-grid .width(6, 12); - } -} - -.giftmessage-order-create { - .field-sender { - margin-top: 1.4rem; - } - .admin__field { // ToDo UI: remove when /app/code/Magento/Backend/view/adminhtml/templates/widget/form.phtml refactored (the wrapping div removed) - margin-bottom: 3rem; - position: relative; - + .admin__field { - margin-top: 1.5rem; - } - } -} - -// -// Totals -// --------------------------------------------- - -.admin__table-secondary { - width: 100%; - td { - padding: .7rem @indent__s; - } - tr:nth-child(2n+1) td { - background-color: @color-white-fog2; - } - .admin__total-amount { - text-align: right; - } - tr:last-child td { - border-bottom: 1px solid @color-gray80; - padding-bottom: @indent__s; - } -} - -.order-totals-actions { - margin-top: @indent__s; - .actions { - margin-top: @indent__l; - text-align: right; - } - .action-default { - &:extend(.abs-action-l all); - } -} - -// ToDo UI: review the collapsible block -//.order-subtotal { -// .summary-collapse { -// cursor: pointer; -// display: inline-block; -// &:before { -// @iconsize: 16px; -// -// background: #f2ebde; -// border: 1px solid #ada89e; -// border-radius: 2px; -// color: #816063; -// content: '+'; -// display: inline-block; -// font-size: @iconsize; -// -webkit-font-smoothing: antialiased; -// font-style: normal; -// font-weight: normal; -// height: @iconsize; -// line-height: @iconsize; -// margin-right: 7px; -// overflow: hidden; -// speak: none; -// text-indent: 0; -// vertical-align: top; -// width: @iconsize; -// } -// &:hover:before { -// background: #cac3b4; -// } -// } -// &.show-details .summary-collapse:before { -// content: '\e03a'; -// } -//} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less new file mode 100644 index 0000000000000000000000000000000000000000..2b4e2e6093170ca6345db320f4240256e67fa8ac --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order.less @@ -0,0 +1,267 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Page components +// --------------------------------------------- + +@import 'order/_address.less'; +@import 'order/_discounts.less'; +@import 'order/_gift-options.less'; +@import 'order/_items.less'; +@import 'order/_order-account.less'; +@import 'order/_payment-shipping.less'; +@import 'order/_sidebar.less'; +@import 'order/_sku.less'; +@import 'order/_total.less'; +@import 'order/_order-comments.less'; + +// +// Variables +// --------------------------------------------- + +@order-create-icon-refresh__font-size: 2rem; +@order-create-icon-refresh__color: @color-gray83; +@order-create-icon-refresh__hover__color: darken(@color-gray83, 10%); + +@order-create-icon-add__content: @icon-arrow-right__content; +@order-create-icon-configure__content: @icon-systems__content; +@order-create-icon-remove__content: @icon-delete__content; +@order-create-icon-reset__content: @icon-remove-small__content; +@order-create-icon-refresh__content: @icon-refresh__content; +@order-create-icon-plus__content: @icon-plus__content; +@order-create-icon-plus__hover__color: @color-very-dark-gray-black2; + +// +// Crosspage components +// _____________________________________________ + +// +// Layout +// --------------------------------------------- + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .order-details { + float: right; + #mix-grid .width(9,12); + margin-left: 0; + } + .order-sidebar { + #mix-grid .column(3,12); + margin-left: 0; + } + + .order-billing-address, + .order-billing-method, + .order-history, + .order-information, + .order-payment-method, + .order-comments-history { + float: left; + #mix-grid .width(6,12); + } + + .order-shipping-address, + .order-shipping-method, + .order-totals, + .order-view-account-information .order-account-information { + float: right; + #mix-grid .width(6,12); + } +} + +.order-view { + > .ui-tabs-panel { + border: 0; + margin: 0; + padding: 0; + } +} + +// +// Page sections +// --------------------------------------------- + +.admin__page-section { + margin-bottom: 5rem; + + .admin__legend { + &:extend(.abs-fieldset-legend all); + } + + .admin__field { + &:extend(.abs-field-rows all); + } + + .admin__control-table-wrapper { + margin-top: @indent__base; + } + + address { + font-style: normal; + } + + .admin__table-secondary { + .admin__control-text { + width: 5.4rem; + } + } +} + +.admin__page-section-title { + &:extend(.abs-clearfix all); + border-bottom: 1px solid @color-gray80; + margin-bottom: 1.7rem; + padding: 1.4rem 0 .5rem; + strong, + .title { + &:extend(h2); + float: left; + margin: 0; + } + .actions { + display: inline-block; + margin-left: @indent__xs; + } +} + +.admin__page-section-content { + &:extend(.abs-clearfix all); +} + +.admin__page-section-item-title, +.admin__page-section-content .admin__page-section-title { + border-bottom: 0; + margin-bottom: 1.5rem; + padding: 0; + .title { + &:extend(.abs-fieldset-legend all); + margin: 0; + } + .actions { + display: inline-block; + margin-left: @indent__xs; + } +} + +// +// Select Customer +// --------------------------------------------- + +.order-customer-selector { + .admin__page-section-title { + .title { + margin: 0 0 2rem; + } + .actions { + float: right; + margin-top: -.5rem; + } + } +} + +// +// Select Store Scope +// --------------------------------------------- + +.tree-store-scope { + max-width: 50rem; + .admin__field { + margin: 0 0 1rem; + } +} + +// +// Order Errors +// --------------------------------------------- + +.order-errors { + .col-qty { + .admin__control-text { + &:extend(.abs-control-qty all); + } + } +} + +// +// Order Invoice +// --------------------------------------------- + +.order-invoice-tables { + &:extend(.abs-order-tables all); + &:extend(.abs-order-tbody-border all); +} + +.abs-qty-table { + th, + td { + border: none; + font-weight: @font-weight__regular; + padding: 0 @order-create-sidebar__margin__s @order-create-sidebar__margin__s 0; + } +} + +.abs-order-tbody-border { + tbody { + border-bottom: 1px solid @table-td__border-color; + &:last-of-type { + border-bottom: none; + } + } +} + + +// +// Product configure popup +// --------------------------------------------- + +.product-configure-popup { + .weee { + .price-excluding-tax, + .price-including-tax { + display: block; + font-size: 1.3rem; + &:before { + content: attr(data-label) ": "; + } + } + } +} + +// ToDo UI: review the collapsible block +//.order-subtotal { +// .summary-collapse { +// cursor: pointer; +// display: inline-block; +// &:before { +// @iconsize: 16px; +// +// background: #f2ebde; +// border: 1px solid #ada89e; +// border-radius: 2px; +// color: #816063; +// content: '+'; +// display: inline-block; +// font-size: @iconsize; +// -webkit-font-smoothing: antialiased; +// font-style: normal; +// font-weight: normal; +// height: @iconsize; +// line-height: @iconsize; +// margin-right: 7px; +// overflow: hidden; +// speak: none; +// text-indent: 0; +// vertical-align: top; +// width: @iconsize; +// } +// &:hover:before { +// background: #cac3b4; +// } +// } +// &.show-details .summary-collapse:before { +// content: '\e03a'; +// } +//} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_address.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_address.less new file mode 100644 index 0000000000000000000000000000000000000000..0fdcfc2df388f9ca7c25a9d9ee78f1715a5dba1d --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_address.less @@ -0,0 +1,49 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Order Address Information +// --------------------------------------------- + +.order-details { + .order-search-items { + .col-qty { + .admin__control-text { + &:extend(.abs-control-qty); + } + } + } + + .order-items, + .order-search-items, + .order-additional-area { + .admin__page-section-title { + .actions { + float: right; + margin-bottom: @order-create-sidebar__margin__reqular; + margin-top: -.3rem; + } + .action-secondary { + margin-left: @indent__base; + } + } + } + + .admin__field-option { + .admin__field-label { + display: block; + width: auto; + } + } +} + +.field-vat-number { + .action-default { + &:extend(.action-tertiary all); + font-weight: @font-weight__regular; + margin-top: @indent__s; + padding: 0; + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_discounts.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_discounts.less new file mode 100644 index 0000000000000000000000000000000000000000..64b80e77823dc8ce8ea8931cc8a587b4d88e5266 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_discounts.less @@ -0,0 +1,67 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Order discounts +// --------------------------------------------- + +.order-discounts { + &:extend(.abs-clearfix all); + margin-top: @indent__base; + .action-secondary { + float: right; + margin-top: 2.1rem; + } + .order-coupons { + float: left; + } + .admin__field { + display: inline-block; + margin: 0 3.5rem 0 0; + vertical-align: top; + + .admin__field-control { + padding-right: 32px; + position: relative; + } + + .action-default { + &:extend(.abs-action-reset all); + position: absolute; + right: 0; + top: 7px; + > span { + .extend__visually-hidden(); + } + + &:before { + &:extend(.abs-icon all); + content: @order-create-icon-add__content; + } + + &:hover { + color: @order-create-icon-plus__hover__color; + } + } + p { + margin: @indent__s 0 0; + } + } + .action-remove { + color: @color-brownie; + margin-left: @indent__xs; + &:hover { + color: @order-create-icon-plus__hover__color; + text-decoration: none; + } + > span { + .extend__visually-hidden(); + } + &:before { + &:extend(.abs-icon all); + content: @order-create-icon-remove__content; + } + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_gift-options.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_gift-options.less new file mode 100644 index 0000000000000000000000000000000000000000..4b88d1f0e57e1074965c264f8a80e69aa6c1ce23 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_gift-options.less @@ -0,0 +1,58 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Gift options +// --------------------------------------------- + +.order-gift-options { + &:extend(.abs-clearfix all); + .card-price-box { + display: none; + &._active { + display: block; + } + } + + .price-box { + .price { + font-weight: @font-weight__bold; + } + } + + > .giftmessage-order-create { + float: left; + #mix-grid .width(6, 12); + } + + .admin__field { + &._required[class] { + &:not(.admin__field-option) { + > .admin__field-label span { + &:after { + margin-left: 0; + } + } + } + } + } +} + +.giftmessage-order-create { + .field-sender { + margin-top: 1.4rem; + } + .admin__field { // ToDo UI: remove when /app/code/Magento/Backend/view/adminhtml/templates/widget/form.phtml refactored (the wrapping div removed) + margin-bottom: 3rem; + position: relative; + + .admin__field { + margin-top: 1.5rem; + } + } +} + +.gift-options-tooltip { + &:extend(.abs-admin__field-tooltip-content all); +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_items.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_items.less new file mode 100644 index 0000000000000000000000000000000000000000..0f621df99f43c72b37991106eaab7880ac6868a7 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_items.less @@ -0,0 +1,124 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// --------------------------------------------- + +@order-create-table__border-color: @table-td__border-color; +@order-create-sku__background: @admin__page-nav__background-color; +@order-create-sku__padding: @indent__base; +@order-create-sku-table__border-color: @color-white; + +// +// Table +// --------------------------------------------- + +.order-tables { + &:extend(.abs-order-tables all); + &:extend(.abs-order-tbody-border all); +} + +.order-items { + > .admin__page-section-title { + margin: 0; + } + .actions-update { + margin: @indent__base 0; + text-align: right; + } +} + +.order-search-items { + .grid { + .action-configure { + float: right; + } + .col-id, + .col-price, + .col-in_products { + width: 10rem; + } + } +} + +.abs-order-tables { + margin: 0 0 @order-create-sidebar__margin__reqular; + width: 100%; + th { + border-top: 0; + font-size: 1.3rem; + } + td { + border-bottom: none; + } + tbody { + tr { + &.row-messages-error, + &.row-gift-options { + td { + padding-top: 0; + } + } + } + } + tfoot { + td { + border-bottom: 1px solid @order-create-table__border-color; + border-top: none; + } + } + .col-qty, + .col-qty-invoice { + .admin__control-text { + &:extend(.abs-control-qty all); + } + } + .qty-table { + &:extend(.abs-qty-table all); + } + .col-actions { + .admin__control-select { + width: 13rem; + } + } + .price { + display: inline-block; + margin: 0 0 @order-create-sidebar__margin__s; + } + .item-options { + &:extend(.abs-clearfix all); + margin: @order-create-sidebar__margin__m 0 0; + dt { + clear: left; + float: left; + margin: 0 @order-create-sidebar__margin__s @order-create-sidebar__margin__s 0; + } + dd { + display: inline-block; + float: left; + margin: 0 0 @order-create-sidebar__margin__s; + } + } + .custom-price-block { + font-size: @order-create-sidebar__font-size__xs; + margin: 0 0 @order-create-sidebar__margin__s; + + .admin__control-text { + &:extend(.abs-control-price); + } + } + .discount-price-block { + font-size: @order-create-sidebar__font-size__xs; + } + .product-configure-block { + margin: @indent__s 0 0; + .disabled { + display: none; + } + } + .product-sku-block { + margin: @indent__s 0 0; + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_order-account.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_order-account.less new file mode 100644 index 0000000000000000000000000000000000000000..a0cf2a04230c41c2028b05acffb070e3f6f3dd1e --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_order-account.less @@ -0,0 +1,24 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Order Account Information +// --------------------------------------------- + +.order-account-information { + .admin__fieldset { + &:extend(.abs-clearfix all); + } + .admin__field { + margin-bottom: 0; + } + .field-group_id { + float: left; + } + .field-email { + margin-top: 0; + overflow: hidden; + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_order-comments.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_order-comments.less new file mode 100644 index 0000000000000000000000000000000000000000..675a02272c8cf1199ab008e1e454ce58cfa3e144 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_order-comments.less @@ -0,0 +1,58 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Edit Order comments +// --------------------------------------------- + +.edit-order-comments { + .note-list { + font-size: @edit-order-comment-notes__font-size; + list-style: none; + margin: 0 0 @order-create-sidebar__margin; + } + .note-list-item { + margin: 0 0 @order-create-sidebar__margin__s; + } + .note-list-date, + .note-list-time { + padding: 0 @order-create-sidebar__margin__m 0 0; + } + .note-list-status, + .note-list-customer { + border-left: 1px solid @edit-order-comment-notes__border-color; + padding: 0 @order-create-sidebar__margin__m; + } + .note-list-customer-notapplicable, + .note-list-customer-not-notified, + .note-list-customer-notified { + font-weight: @font-weight__bold; + padding: 0 @order-create-sidebar__margin__m 0 0; + } + .note-list-comment { + margin: 0 0 @order-create-sidebar__margin__reqular; + } + .comments-block-item { + margin: 0 0 @order-create-sidebar__margin; + } + .comments-block-item-comment { + margin: 0 0 @order-create-sidebar__margin__s; + } + .comments-block-item-date-time { + font-size: @font-size__tiny; + } +} + +.edit-order-comments-block-title { + margin: 0 0 @order-create-sidebar__margin; + .typography( + @_font-size: 1.9rem, + @_color: @color-brown-darkie, + @_font-weight: @font-weight__semibold, + @_line-height: @line-height__s, + @_font-family: false, + @_font-style: false + ); +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_payment-shipping.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_payment-shipping.less new file mode 100644 index 0000000000000000000000000000000000000000..fe3ebac483461cb7bd0f7899d679e2808a5dfb5b --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_payment-shipping.less @@ -0,0 +1,91 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Order Payment & Shipping Information +// --------------------------------------------- + +.admin__payment-method-wapper { + margin: 0; + .admin__field { + margin-left: -4rem; + &:first-child { + margin-top: 1.5rem; + } + } + .admin__payment-methods { + margin: 0; + } +} + +.admin__order-shipment-methods-title { + font-weight: @font-weight__bold; + margin: 0 0 @indent__xs; +} + +.admin__order-shipment-methods-options { + margin: 0 0 @indent__base; +} + +.admin__order-shipment-methods-options-list { + list-style: none; + margin: 0; +} + +.order-shipping-method-summary { + padding-top: @field-option__padding-top; +} + +.order-shipping-method, +.order-billing-method { + position: relative; +} + +.order-shipping-method-summary, +.order-shipping-method-info { + .action-default { + &:extend(.action-tertiary all); + font-weight: @font-weight__regular; + padding: 0; + } +} + +.order-methods-overlay { + background-color: rgba(255, 255, 255, .5); + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; + span { + background-color: @color-white; + display: block; + font-weight: @font-weight__bold; + left: 0; + padding: @indent__xs 0; + position: absolute; + top: 43px; + } + .order-shipping-address & { + span { + top: 22px; + } + } +} + +.shipping-description-wrapper { + .price { + font-weight: @font-weight__bold; + } +} + +.order-payment-method-title, +.shipping-description-title { + font-weight: @font-weight__bold; +} + +.action-create-label { + margin: @indent__s 0; +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create-sidebar.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_sidebar.less similarity index 88% rename from app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create-sidebar.less rename to app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_sidebar.less index 6bdd17f7f4d18eae84eba64d3fe9e1b5cdbcfb20..8ef7ff03c7c529c3e4ad388073672207a1917107 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/_order-create-sidebar.less +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_sidebar.less @@ -8,19 +8,17 @@ // --------------------------------------------- @order-create-sidebar__font-size: 1.5rem; -@order-create-sidebar__font-size-xs: 1.1rem; +@order-create-sidebar__font-size__xs: 1.1rem; @order-create-sidebar__color: @color-very-dark-gray; @order-create-sidebar__margin: 2.4rem; @order-create-sidebar__padding: @indent__base; -@order-create-sidebar__margin-small: .5rem; -@order-create-sidebar__margin-m: 1rem; -@order-create-sidebar__margin-reqular: 1.7rem; +@order-create-sidebar__margin__s: .5rem; +@order-create-sidebar__margin__m: 1rem; +@order-create-sidebar__margin__reqular: 1.7rem; @order-create-sidebar__border-color: @border__color; @order-create-sidebar-scroll__height: 24rem; -// - // // Order Sidebar // --------------------------------------------- @@ -47,7 +45,7 @@ padding: 0 0 @order-create-sidebar__margin; } .admin__control-select { - margin: 0 0 @order-create-sidebar__margin-small; + margin: 0 0 @order-create-sidebar__margin__s; width: 100%; } .order-sidebar-block { @@ -55,7 +53,7 @@ margin: 0 0 @order-create-sidebar__margin; padding: 0 0 @order-create-sidebar__margin; } - .table-info { + .admin__table-primary { color: @order-create-sidebar__color; width: 100%; th, @@ -102,7 +100,7 @@ text-align: right; .icon-configure, .icon-add { - margin-right: @order-create-sidebar__margin-m; + margin-right: @order-create-sidebar__margin__m; } } } @@ -110,7 +108,7 @@ &:extend(.abs-icon all); display: table-cell; font-size: @order-create-icon-refresh__font-size; - padding-right: @order-create-sidebar__margin-m; + padding-right: @order-create-sidebar__margin__m; vertical-align: middle; &:after { color: @order-create-icon-refresh__color; @@ -127,16 +125,16 @@ } } .create-order-sidebar-block { - .head { + .sidebar-title-block { margin: 0 0 @order-create-sidebar__margin; } .auto-scroll { - margin: 0 -@order-create-sidebar__padding @order-create-sidebar__margin-small; + margin: 0 -@order-create-sidebar__padding @order-create-sidebar__margin__s; max-height: @order-create-sidebar-scroll__height; overflow: auto; position: relative; + .action-default { - margin-top: @order-create-sidebar__margin-reqular; + margin-top: @order-create-sidebar__margin__reqular; } .no-items { padding-left: @order-create-sidebar__padding; @@ -153,7 +151,7 @@ margin: 0; vertical-align: middle; + .admin__control-select { - margin-top: @order-create-sidebar__margin-reqular; + margin-top: @order-create-sidebar__margin__reqular; } } .actions { diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_sku.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_sku.less new file mode 100644 index 0000000000000000000000000000000000000000..68b25e5aa12ae0ad94526499174c2418ed3a5413 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_sku.less @@ -0,0 +1,45 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Add by SKU +// --------------------------------------------- + +.add-by-sku-wrapper { + .add-by-sku { + margin: 0 0 @indent__base; + } + .admin__field-note { + margin: 1.4rem 0; + } + .action-reset { + &:extend(.abs-action-reset all); + &:extend(.abs-icon all); + display: inline-block; + font-size: 1.6rem; + margin: -.4rem 0 0; + opacity: .5; + vertical-align: middle; + &:after { + color: @order-create-icon-reset__content; + content: @order-create-icon-reset__content; + } + &:hover { + opacity: 1; + &:after { + color: @order-create-icon-plus__hover__color; + } + } + > span { + &:extend(.abs-visually-hidden all); + } + } + .col-qty { + width: 8rem; + .admin__control-text { + &:extend(.abs-control-qty all); + } + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_total.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_total.less new file mode 100644 index 0000000000000000000000000000000000000000..699576bde84c70e2645fbe07475fbe915afca647 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_total.less @@ -0,0 +1,19 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Totals +// --------------------------------------------- + +.order-totals-actions { + margin-top: @indent__s; + .actions { + margin-top: @indent__l; + text-align: right; + } + .action-default { + &:extend(.abs-action-l all); + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Shipping/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Shipping/web/css/source/_module.less new file mode 100644 index 0000000000000000000000000000000000000000..c1ff50783ee7816d1751695366462a40901c383a --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Shipping/web/css/source/_module.less @@ -0,0 +1,114 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Order Shipment +// --------------------------------------------- + +.order-shipment-table { + &:extend(.abs-order-tables all); + &:extend(.abs-order-tbody-border all); +} + +// +// Packaging for Shipping Popup +// -------------------------------------- + +// ToDo UI: refactor the popup to jQuery UI, edit the styles +.packaging-window { + background: @color-white; + box-shadow: 0 3px 6px rgba(0, 0, 0, .4); + left: 50%; + margin: -20rem 0 0 -47rem; + position: fixed; + top: 50%; + width: 100rem; + z-index: 1000; + .message-warning { + margin: 0 0 @indent__s; + } + .admin__control-select { + width: 13rem; + &.measures { + width: 9rem; + } + } + .packaging-content { + height: auto !important; + max-height: 40rem; + overflow-x: hidden; + overflow: auto; + padding: @indent__base @indent__base 0; + position: relative; + .options-weight { + vertical-align: top; + } + } + .popup-window-title { + &:extend(.abs-clearfix all); + padding: @indent__base; + .title { + font-size: 1.9rem; + display: block; + } + .actions { + float: right; + } + } + .popup-fieldset-title { + &:extend(.abs-clearfix all); + .title { + display: block; + font-weight: 700; + padding-top: @indent__s; + } + .actions { + float: right; + } + margin: 0 0 @indent__base; + } + .popup-window-buttons-set { + padding: @indent__base; + text-align: right; + } + .package-add-products { + margin: @indent__base 0 0; + .grid { + padding: 0; + button { + vertical-align: middle; + } + } + } + .col-total-weight { + .admin__control-text { + margin: 0 0 .5rem; + } + } + .col-qty-edit { + .admin__control-text { + &:extend(.abs-control-qty all); + } + } + .col-actions { + width: 13rem; + .action-delete { + padding-top: 0; + } + } + .admin__table-primary { + .action-delete { + margin-top: -.7rem; + padding: 0; + &:extend(.abs-action-delete all); + } + } + .action-secondary { + float: right; + } + .action-close { + &:extend(.abs-action-tertiary all); + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/_module.less new file mode 100644 index 0000000000000000000000000000000000000000..6ab7104603ae2c6e9a7f1bfbbe30ef029520c508 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/_module.less @@ -0,0 +1,6 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +@import 'module/_data-grid.less'; diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module.less index 6d1cdd4c54a3d3db423a4740e016c242f7fd7e84..3e1c86ab7f8b8dbd8cd4cbcecc88cf50ae9d5af0 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module.less @@ -3,13 +3,15 @@ // * See COPYING.txt for license details. // */ -//colors +// +// Variables +// --------------------------------------------- + @admin__color1: #adadad; @admin__color2: #d3d3d3; @admin__color3: #e0e0e0; @admin__color4: #666; -//Spacing @spacing__base: 10px; @spacing-xs: @spacing__base; @spacing-s: @spacing__base; @@ -17,7 +19,6 @@ @spacing-l: @spacing__base; @spacing-xl: @spacing__base; -//Fonts @size__base: 1rem; @size-xs: @size__base; @size-s: @size__base; @@ -27,6 +28,8 @@ @field-date-icon--color: #514943; +// + [class*="tab-nav-item"]:not(ul):active, [class*="tab-nav-item"]:not(ul):focus { box-shadow: none; @@ -125,53 +128,51 @@ } .listing-tiles { - overflow: hidden; - margin-top: -10px; - margin-left: -10px; - - .listing-tile { - background-color: #f2ebde; - display: block; - width: 238px; - height: 200px; - float: left; - border: 1px solid #676056; - margin-top: 10px; - margin-left: 10px; - border-radius: 4px; - text-align: center; - - &.disabled { - border-color: red; - } + overflow: hidden; + margin-top: -10px; + margin-left: -10px; + + .listing-tile { + background-color: #f2ebde; + display: block; + width: 238px; + height: 200px; + float: left; + border: 1px solid #676056; + margin-top: 10px; + margin-left: 10px; + border-radius: 4px; + text-align: center; + + &.disabled { + border-color: red; + } - &.enabled { - border-color: green; + &.enabled { + border-color: green; + } } - } } .listing { - .disabled { - color: red; - } - .enabled { - color: green; - } + .disabled { + color: red; + } + .enabled { + color: green; + } } .pager { text-align: left; padding-bottom: 10px; .clearfix(); - [data-part=left] { display: inline-block; width: 45%; float: left; text-align: left; } - [data-part=right] { display: inline-block; width: 45%; @@ -182,44 +183,30 @@ -ms-user-select: none; // use in 11 IE user-select: none; } - - .action-next{ + .action-next { cursor: pointer; } - - .action-previous{ + .action-previous { cursor: pointer; } } -.pager { - text-align: left; -} -.pager [data-part=left] { - display: inline-block; - width: 45%; - text-align: left; -} -.pager [data-part=right] { - display: inline-block; - width: 45%; - text-align: right; - float: right; -} -.grid .col-title { - min-width: 90px; - text-align: center; -} -.grid-actions [data-part=search] { - display: inline-block; - margin: 0 30px; -} -.grid-actions [data-part=search] input[type=text] { - vertical-align: bottom; - width: 460px; +.grid-actions { + [data-part=search] { + display: inline-block; + margin: 0 30px; + input[type=text] { + vertical-align: bottom; + width: 460px; + } + } } .grid { + .col-title { + min-width: 90px; + text-align: center; + } .actions-split { .clearfix(); display: inline-block; @@ -292,274 +279,6 @@ } } -.filters { - &-toggle { - .button( - @_button-margin: 3px, - @_button-icon-use: true, - @_button-font-content: @icon-pointer-down, - @_button-icon-font-size: 30px, - @_button-icon-font-line-height: 15px, - @_button-icon-font-text-hide: false, - @_button-icon-font-position: after - ); - .button-reset(); - &:after { - margin-top: 2px; - margin-left: -3px; - } - &.active { - &:after { - content: @icon-pointer-up; - } - } - } - &-current { - padding: 10px 0; - display: none; - &.active{ - display: block; - } - } - &-items { - .list-reset-styles(); - display: inline; - } - &-item { - display: inline-block; - margin:0 5px 5px 0; - padding: 2px 2px 2px 4px; - border-radius: 3px; - background: #f7f3eb; - .item-label { - font-weight: 600; - &:after { - content: ": " - } - } - .action-remove { - .button( - @_button-margin: 3px, - @_button-icon-use: true, - @_button-font-content: @icon-remove, - @_button-icon-font-size: 16px, - @_button-icon-font-line-height: 16px, - @_button-icon-font-text-hide: true - ); - padding: 0; - //.button-reset(); - } - } - &-form { - position: relative; - z-index: 1; - margin: 14px 0; - background: #fff; - border: 1px solid #bbb; - box-shadow: 0 3px 3px rgba(0, 0, 0, .15); - .action-close { - position: absolute; - top: 3px; - right: 7px; - .button( - @_button-margin: 3px, - @_button-icon-use: true, - @_button-font-content: @icon-remove, - @_button-icon-font-size: 42px, - @_button-icon-font-line-height: 42px, - @_button-icon-font-text-hide: true - ); - .button-reset(); - } - } - &-actions { - margin: 18px; - text-align: right; - } - &-fieldset { - padding-bottom: 0; - .field { - border: 0; - .form-field( - @_type: inline, - @_column: true, - @_column-number: 3, - @_type-inline-label-width: 35%, - @_type-inline-control-width: 65% - ); - .label { - .style2(); - margin: 0; - } - } - } - .field-date .group { - .hasDatepicker { - width: 100%; - padding-right: 30px; - - & + .ui-datepicker-trigger { - img { - display: none; - } - .button-reset(); - .icon-font( - @icon-calendar, - @_icon-font-size: 35px, - @_icon-font-line-height: 30px, - @_icon-font-text-hide: true, - @_icon-font-position: after, - @_icon-font-color: @field-date-icon--color - ); - margin-left: -33px; - display: inline-block; - width: 30px; - } - } - } - .field-range .group{ - .field { - margin-bottom: 0; - } - .label { - &:extend(.visually-hidden all); - } - .control { - width: 100%; - box-sizing: border-box; - padding-right: 0; - position: relative; - z-index: 1; - } - } - -} - -/* [data-part=filter-form] { - width: 650px; - left: 150px; - - background: #fff; - border: 1px solid #bbb; - position: absolute; - z-index: 100; - box-shadow: 0 3px 3px rgba(0, 0, 0, .15); - margin-top: 4px; - - .title { - position: relative; - padding: 5px 18px; - - .close { - position: absolute; - font-size: .8em; - right: 10px; - top: 12px; - cursor: pointer; - - &:hover, - &:active { - text-decoration: underline; - } - } - } - - > .actions { - padding: 5px 18px 36px; - } -} */ - -.mass-select { - position: relative; - margin: -6px -10px; - padding: 6px 2px 6px 10px; - z-index: 1; - white-space: nowrap; - &.active { - background: rgba(0,0,0,.2); - } - &-toggle { - .button( - @_button-margin: 3px, - @_button-icon-use: true, - @_button-font-content: @icon-pointer-down, - @_button-icon-font-size: 30px, - @_button-icon-font-line-height: 15px, - @_button-icon-font-text-hide: true - ); - .button-reset(); - &:before { - margin-top: -2px; - text-indent: -5px; - color: #fff; - } - &:hover:before { - color: #fff; - } - &:active, - &.active { - &:before { - content: @icon-pointer-up; - } - } - } - &-field { - .label { - &:extend(.visually-hidden all); - } - display: inline; - } - &-menu { - display: none; - position: absolute; top: 100%; left: 0; - text-align: left; - .list-reset-styles(); - background: #fff; - border: 1px solid #bbb; - min-width: 175px; - box-shadow: 0 3px 3px rgba(0, 0, 0, .15); - li { - margin: 0; - padding: 4px 15px; - border-bottom: 1px solid #e5e5e5; - } - li:hover { - background: #e8e8e8; - cursor: pointer; - } - span { - font-weight: normal; - font-size: 13px; - color: #645d53; - } - &.active { - display: block; - } - } -} - -.grid-loading-mask{ - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - background: rgba(255, 255, 255, .5); - z-index: 100; - - .grid-loader{ - position: absolute; - margin: auto; - left: 0; - top: 0; - right: 0; - bottom: 0; - width: 218px; - height: 149px; - background: url('@{baseDir}images/loader-2.gif') 50% 50% no-repeat; - } -} - // // Form Component // @@ -581,20 +300,20 @@ } .field-price.addon { - direction: rtl; + direction: rtl; } .field-price.addon > * { - direction: ltr; + direction: ltr; } .field-price.addon .addafter { - border-width: 1px 0 1px 1px; - border-radius: 2px 0 0 2px; + border-width: 1px 0 1px 1px; + border-radius: 2px 0 0 2px; } .field-price.addon input:first-child { - border-radius: 0 2px 2px 0; + border-radius: 0 2px 2px 0; } .field-price input[type="text"] { @@ -602,21 +321,21 @@ } .field-price input ~ label.addafter strong { - margin-left: 2px; - margin-right: -2px; + margin-left: 2px; + margin-right: -2px; } .field-price.addon > input { - width: 99px; - float: left; + width: 99px; + float: left; } .field-price .control { - position: relative; + position: relative; } .field-price label.mage-error { - position: absolute; - left: 0; - top: 30px; + position: absolute; + left: 0; + top: 30px; } diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less new file mode 100644 index 0000000000000000000000000000000000000000..d01685e141655100c6a45d8a9115fcf4ae3d7abf --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less @@ -0,0 +1,313 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// UI -> Data Grid +// _____________________________________________ + +// +// Components +// --------------------------------------------- + +@import 'data-grid/_data-grid-header.less'; + +// +// Variables +// --------------------------------------------- + +@data-grid__font-size: 1.3rem; + +@data-grid-tr__active__background-color: @action__hover__background-color; +@data-grid-tr__hover__background-color: lighten(@action__hover__background-color, 1%); + +@data-grid-cell__border-width: .1rem; +@data-grid-cell__padding-horizontal: 1rem; +@data-grid-cell__padding-vertical: 1rem; + +@data-grid-td__border-color: @color-gray84; +@data-grid-td__border-inner-style: dashed; +@data-grid-td__border-outer-style: solid; +@data-grid-td__even__background-color: @color-white-smoke; +@data-grid-td__odd__background-color: @page__background-color; + +@data-grid-th__border-color: @color-darkie-gray; +@data-grid-th__border-style: solid; +@data-grid-th__background-color: @color-brownie; +@data-grid-th__color: @color-white; +@data-grid-th__padding-horizontal: @data-grid-cell__padding-horizontal; +@data-grid-th__padding-vertical: @data-grid-cell__padding-vertical; +@data-grid-th__hover__background-color: lighten(@data-grid-th__background-color, 5%); + +@data-grid-th-marker__width: .7rem; + +@data-grid-checkbox-cell-inner__padding-top: 1.1rem; +@data-grid-checkbox-cell-inner__padding-horizontal: 1.8rem; + +@data-grid-row-parent-marker__size: 1rem; + +// + +.admin__data-grid-wrap { + padding-top: 0; + position: relative; +} + +.admin__data-grid-loading-mask { + background: rgba(255, 255, 255, .5); + bottom: 0; + left: 0; + right: 0; + top: 0; + position: absolute; + z-index: @overlay__z-index; + + .grid-loader { + background: url('@{baseDir}images/loader-2.gif') 50% 50% no-repeat; + bottom: 0; + height: 149px; + left: 0; + margin: auto; + position: absolute; + right: 0; + top: 0; + width: 218px; + } +} + +.data-grid { + border-bottom: @data-grid-cell__border-width @data-grid-td__border-outer-style @data-grid-td__border-color; + border-left: none; + border-right: none; + border-top: none; + font-size: @data-grid__font-size; + margin-bottom: 2rem; + max-width: 100%; + width: 100%; + thead { + background-color: transparent; // ToDo UI: Rewrite old styles. Should be deleted afterwards + color: @text__color; // ToDo UI: Rewrite old styles. Should be deleted afterwards + } + tr { + &:nth-child(even) { + td { + background-color: @data-grid-td__even__background-color; + } + } + &:active { + td { + background-color: @data-grid-tr__active__background-color; + } + } + &:hover { + td { + background-color: @data-grid-tr__hover__background-color; + cursor: pointer; + } + } + &.data-grid-tr-no-data { + &:hover { + td { + cursor: default; + background-color: @data-grid-td__odd__background-color; + } + } + } + } + th, + td { + font-size: @data-grid__font-size; // ToDo UI: Rewrite old styles. Should be deleted afterwards + line-height: @line-height__base; + transition: @smooth__background-color; + vertical-align: top; + } + td { + background-color: @data-grid-td__odd__background-color; + border-left: @data-grid-cell__border-width @data-grid-td__border-inner-style @data-grid-td__border-color; + border-right: @data-grid-cell__border-width @data-grid-td__border-inner-style @data-grid-td__border-color; + color: @table__color; + padding: @data-grid-cell__padding-vertical @data-grid-cell__padding-horizontal; + &:first-child { + border-left-style: @data-grid-td__border-outer-style; + } + &:last-child { + border-right-style: @data-grid-td__border-outer-style; + } + // Action select data grid styles (can be action-select-secondary in future) + .action-select { + .link-pattern(); + background-color: transparent; + border: none; + font-size: @data-grid__font-size; + padding: 0 3rem 0 0; + &:hover { + &:after { + border-color: @link__hover__color transparent transparent transparent; + } + } + &:after { + border-color: @link__color transparent transparent transparent; + } + &:before { + display: none; + } + } + .action-menu { + left: auto; + z-index: 1; + } + } + th { + background-color: @data-grid-th__background-color; + border: @data-grid-cell__border-width @data-grid-th__border-style @data-grid-th__border-color; + border-left-color: transparent; + color: @data-grid-th__color; + font-weight: @font-weight__semibold; + padding: 0; + text-align: left; + &:first-child { + border-left-color: @data-grid-th__border-color; + } + } + .data-grid-th { + color: @data-grid-th__color; + padding: @data-grid-th__padding-vertical @data-grid-th__padding-horizontal; + &._sortable { + cursor: pointer; + padding-right: @data-grid-th__padding-horizontal * 2 + @data-grid-th-marker__width; + position: relative; + transition: @smooth__background-color; + &:focus, + &:hover { + background-color: @data-grid-th__hover__background-color; + } + &:active { + padding-bottom: @data-grid-th__padding-vertical - .1rem; + padding-top: @data-grid-th__padding-vertical + .1rem; + } + } + } + .data-grid-checkbox-cell { + padding: 0; + &:hover { + cursor: default; + } + } + .data-grid-multiselect-cell { + padding: @data-grid-th__padding-horizontal @data-grid-th__padding-vertical @data-grid-th__padding-horizontal - .1rem; + text-align: center; + width: @control-checkbox-radio__size + @data-grid-checkbox-cell-inner__padding-horizontal * 2; + } + .data-grid-actions-cell { + padding-left: @data-grid-cell__padding-horizontal * 2; + padding-right: @data-grid-cell__padding-horizontal * 2; + width: 1%; + } + // Nested rows + .data-grid-row-parent { + &._active { + > td { + background-color: @color-lazy-sunny; + border-bottom: @data-grid-cell__border-width @data-grid-td__border-outer-style @data-grid-td__border-color; + border-left-color: transparent; + border-right-color: transparent; + border-top: @data-grid-cell__border-width @data-grid-td__border-outer-style @data-grid-td__border-color; + &:first-child { + border-left-color: @data-grid-td__border-color; + } + &:last-child { + border-right-color: @data-grid-td__border-color; + } + } + } + } + .data-grid-row-child { + display: none; + &._active { + display: table-row; + + tr { + &:not(.data-grid-row-child) { + td { + border-top: @data-grid-cell__border-width @data-grid-td__border-outer-style @data-grid-td__border-color; + } + } + } + } + } + .data-grid-row-child, + .data-grid-row-parent ~ .data-grid-row-child { + td { + background-color: @color-lazy-sun-white; + border-color: transparent; + &:first-child { + border-left-color: @data-grid-td__border-color; + } + &:last-child { + border-right-color: @data-grid-td__border-color; + } + } + } +} + +// Ascend & Descend sort marker +.data-grid-th { + &._sortable { + &._ascend, + &._descend { + &:before { + position: absolute; + right: @data-grid-th__padding-horizontal; + top: @data-grid-th__padding-vertical - .1rem; + } + } + &._ascend { + &:before { + content: '\2193'; + } + } + &._descend { + &:before { + content: '\2191'; + } + } + } +} + +// Checkbox actions column +.data-grid-checkbox-cell-inner { + display: block; + padding: @data-grid-checkbox-cell-inner__padding-top @data-grid-checkbox-cell-inner__padding-horizontal .9rem; + text-align: right; + &:hover { + cursor: pointer; + } +} + +// Nested rows +.data-grid-row-parent { + &._active { + > td { + .data-grid-checkbox-cell-inner { + &:before { + content: @icon-caret-up__content; + } + } + } + } + > td { + .data-grid-checkbox-cell-inner { + padding-left: (@data-grid-checkbox-cell-inner__padding-horizontal * .75) * 2 + @data-grid-row-parent-marker__size; + position: relative; + &:before { + &:extend(.abs-icon all); + content: @icon-caret-down__content; + font-size: @data-grid-row-parent-marker__size; + font-weight: @font-weight__bold; + left: @data-grid-checkbox-cell-inner__padding-horizontal * .75; + position: absolute; + top: @data-grid-checkbox-cell-inner__padding-top + (@data-grid-row-parent-marker__size / 2); + } + } + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/_data-grid-header.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/_data-grid-header.less new file mode 100644 index 0000000000000000000000000000000000000000..6d5ecd492f8b61b3727d2aea729e31e3cce18dbb --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/_data-grid-header.less @@ -0,0 +1,96 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// UI -> Data Grid -> Header +// _____________________________________________ + +// +// Components +// --------------------------------------------- + +@import 'data-grid-header/_data-grid-filters.less'; +@import 'data-grid-header/_data-grid-pager.less'; +// Actions group +@import 'data-grid-header/_data-grid-action-bookmarks.less'; +@import 'data-grid-header/_data-grid-action-columns.less'; + +// +// Variables +// --------------------------------------------- + +@data-grid-header-add-indent__bottom: .9rem; +@data-grid-header-add-indent__top: .5rem; + +@data-grid-header-row__margin-bottom: @indent__base; + +@data-grid-action__z-index: @data-grid-header__z-index - 10; + +// + +.admin__data-grid-header { + font-size: @font-size__base; // ToDo UI: should be deleted, added to prevent fz override with .grid + position: relative; + z-index: @data-grid-header__z-index - 1; +} + +.admin__data-grid-header-row { + &:extend(.abs-clearfix all); + margin-bottom: @data-grid-header-row__margin-bottom; + &:first-child { + margin-bottom: @data-grid-header-row__margin-bottom - @data-grid-header-add-indent__bottom; + } + .action-select-wrap { + display: block; + } + .action-select { + width: 100%; + } +} + +// +// Data grid Header Actions group +// --------------------------------------------- + +.admin__data-grid-actions-wrap { + float: right; + margin-left: 1.1rem; + margin-top: -@data-grid-header-add-indent__top; + text-align: right; + .admin__action-dropdown-wrap { + position: relative; + text-align: left; + &._active, + &._active + .admin__action-dropdown-wrap, // ToDo UI: remove after bookmarks ready + &._hide + .admin__action-dropdown-wrap, + &:first-child { + &:after { + display: none; + } + } + &._active { + .admin__action-dropdown, + .admin__action-dropdown-menu { + border-color: @action__border-color; + } + } + &:after { + border-left: 1px solid @color-gray80; + content: ''; + height: @action__height; + left: 0; + position: absolute; + top: @data-grid-header-add-indent__top; + z-index: 3; + } + } + .admin__action-dropdown { + padding-bottom: @action-dropdown__padding-bottom + @data-grid-header-add-indent__bottom; + padding-top: @action-dropdown__padding-top + @data-grid-header-add-indent__top; + &:after { + margin-top: -.4rem; + } + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-bookmarks.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-bookmarks.less new file mode 100644 index 0000000000000000000000000000000000000000..6e3be82858c0933375b870d9c25d4ccbf986e401 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-bookmarks.less @@ -0,0 +1,160 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// UI -> Data Grid -> Header -> Action Default View +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@action-dropdown-menu__font-size: 1.3rem; + +@action-dropdown-menu-item__background-color: @page-wrapper__background-color; +@action-dropdown-menu-item__padding-vertical: 1rem; +@action-dropdown-menu-item__padding-left: 2rem; +@action-dropdown-menu-item__hover__background-color: @color-gray89; + +@action-dropdown-menu-item-actions__size: 1.7rem; +@action-dropdown-menu-item-actions__width: 5rem; + +@action-dropdown-menu-item-action-icon__padding-horizontal: 1.4rem; +@action-dropdown-menu-item-action-icon__padding-vertical: .6rem; + +// + +.admin__data-grid-action-bookmarks { + .admin__action-dropdown-menu__align(right); + opacity: @component-modal__opacity; + &._hide { + display: none; + } + &._active { + z-index: @data-grid-action__z-index; + } + .admin__action-dropdown { + &:before { + &:extend(.abs-icon all); + content: @icon-views__content; + } + } + .admin__action-dropdown-menu { + font-size: @action-dropdown-menu__font-size; + left: 0; + padding: 1rem 0 0; + right: auto; + > li { + padding: 0 @action-dropdown-menu-item-actions__width 0 0; + position: relative; + white-space: nowrap; + &:not(.action-dropdown-menu-item-last) { + transition: @smooth__background-color; + &:hover { + background-color: @action-dropdown-menu-item__hover__background-color; + } + } + } + .action-dropdown-menu-item { + max-width: 23rem; + min-width: 18rem; + white-space: normal; + word-break: break-all; + } + .action-dropdown-menu-item-edit { + display: none; + padding-bottom: @action-dropdown-menu-item__padding-vertical; + padding-left: @action-dropdown-menu-item__padding-left / 2; + padding-top: @action-dropdown-menu-item__padding-vertical; + .action-dropdown-menu-item-actions { + padding-bottom: @action-dropdown-menu-item__padding-vertical; + padding-top: @action-dropdown-menu-item__padding-vertical; + } + } + // Save action + .action-dropdown-menu-item-last { + padding-bottom: @action-dropdown-menu-item__padding-vertical; + padding-left: @action-dropdown-menu-item__padding-left / 2; + padding-top: @action-dropdown-menu-item__padding-vertical; + > a { + .link-pattern(); + display: inline-block; + padding-left: 1.1rem; + } + } + // Edit state + ._edit { + .action-dropdown-menu-item { + display: none; + } + .action-dropdown-menu-item-edit { + display: block; + } + } + // Edit item + .admin__control-text { + font-size: @action-dropdown-menu__font-size; + min-width: 15rem; + width: ~'calc(100% - 4rem)'; + .ie9 & { + width: 15rem; + } + } + .action-dropdown-menu-item-actions { + border-left: 1px solid @action-dropdown-menu-item__background-color; + bottom: 0; + position: absolute; + right: 0; + top: 0; + width: @action-dropdown-menu-item-actions__width; + } + .action-dropdown-menu-link { + .action-dropdown-menu-link-pattern(); + padding: @action-dropdown-menu-item__padding-vertical 1rem @action-dropdown-menu-item__padding-vertical @action-dropdown-menu-item__padding-left + .1rem; + } + } + // Icon actions + .action-submit, + .action-delete, + .action-edit { + .action-reset(); + vertical-align: top; + &:before { + &:extend(.abs-icon all); + font-size: @action-dropdown-menu-item-actions__size; + } + > span { + .hidden(); + } + } + .action-delete, + .action-edit { + padding: @action-dropdown-menu-item-action-icon__padding-vertical @action-dropdown-menu-item-action-icon__padding-horizontal; + &:active { + .scale(); + } + } + .action-submit { + padding: @action-dropdown-menu-item-action-icon__padding-vertical 1rem @action-dropdown-menu-item-action-icon__padding-vertical .8rem; + &:active { + position: relative; + right: -1px; + } + &:before { + content: @icon-arrow-right__content; + } + } + .action-delete { + &:before { + content: @icon-delete__content; + } + } + .action-edit { + padding-top: @action-dropdown-menu-item-action-icon__padding-vertical + .2rem; + &:before { + content: @icon-edit__content; + } + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-columns.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-columns.less new file mode 100644 index 0000000000000000000000000000000000000000..e4148e87f4dbb11469b2e3ecb97513defca1e363 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-columns.less @@ -0,0 +1,94 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// UI -> Data Grid -> Header -> Action Columns +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@data-grid-action-columns-menu__padding-horizontal: 3.5rem; + +@data-grid-action-columns-menu-item__column: 3; +@data-grid-action-columns-menu-item__margin-bottom: 1.5rem; +@data-grid-action-columns-menu-item__width: 15.8rem; +@data-grid-action-columns-menu-item__height: round((@font-size__base * @line-height__base), 1); + +@data-grid-action-columns-menu-items-to-scroll: 18; +@data-grid-action-columns-menu-scroll__width: 1.8rem; + +// + +.admin__data-grid-action-columns { + &._active { + opacity: @component-modal__opacity; + z-index: @data-grid-action__z-index; + } + .admin__action-dropdown { + &:before { + &:extend(.abs-icon all); + content: @icon-systems__content; + font-size: 1.8rem; // Static + left: .3rem; + margin-right: .7rem; + vertical-align: top; + } + } +} + +.admin__data-grid-action-columns-menu { + color: @color-very-dark-gray-black; + font-size: 1.3rem; + overflow: hidden; + padding: 2.2rem @data-grid-action-columns-menu__padding-horizontal 1rem; + z-index: 1; + // State with scroll when .admin__field-option > @data-grid-action-columns-menu-items-to-scroll + &._overflow { + .admin__action-dropdown-menu-header { + border-bottom: 1px solid @border-color__base; + } + .admin__action-dropdown-menu-content { + width: @data-grid-action-columns-menu-item__width * @data-grid-action-columns-menu-item__column + @data-grid-action-columns-menu-scroll__width; + } + .admin__action-dropdown-menu-footer { + border-top: 1px solid @border-color__base; + padding-top: 2.5rem; + } + } + .admin__action-dropdown-menu-content { + .extend__clearfix(); + max-height: (@data-grid-action-columns-menu-items-to-scroll / @data-grid-action-columns-menu-item__column) * (@data-grid-action-columns-menu-item__height + @data-grid-action-columns-menu-item__margin-bottom) + (@data-grid-action-columns-menu-item__height / 2 + @data-grid-action-columns-menu-item__margin-bottom); + overflow-y: auto; + padding-top: 1.5rem; + width: @data-grid-action-columns-menu-item__width * @data-grid-action-columns-menu-item__column; + } + .admin__field-option { + height: @data-grid-action-columns-menu-item__height; + float: left; + margin-bottom: @data-grid-action-columns-menu-item__margin-bottom; + padding: 0 1rem 0 0; + width: @data-grid-action-columns-menu-item__width; + } + .admin__field-label { + .text-overflow-ellipsis(); + display: block; + } + .admin__action-dropdown-menu-header { + padding-bottom: 1.5rem; + } + .admin__action-dropdown-menu-footer { + padding: 1rem 0 2rem; + } + .admin__action-dropdown-footer-main-actions { + margin-left: 25%; + text-align: right; + } + .admin__action-dropdown-footer-secondary-actions { + float: left; + margin-left: -@button__padding-horizontal; + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-filters.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-filters.less new file mode 100644 index 0000000000000000000000000000000000000000..66df9bda92aaebd8b110229fdbcb6adefc9b2e79 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-filters.less @@ -0,0 +1,320 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// UI -> Data Grid -> Header -> Filters +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@data-grid-search-action__size: 2rem; + +@data-grid-filters__font-size: 1.3rem; +@data-grid-filters__background-color: @page-wrapper__background-color; + +@data-grid-filters-fieldset__inner-side: 4rem; +@data-grid-filters-fieldset__columns: 4; + +@data-grid-filters-label__width: 25%; + +@data-grid-filters-action__padding-right: 2.1rem; +@data-grid-filters-action__padding-left: 1.7rem; +@data-grid-filters-action__active__border-color: @color-gray80; +@data-grid-filters-action__active__color: @color-phoenix; + +@data-grid-filters-current-action-remove__background-color: @color-gray68; +@data-grid-filters-current-action-remove__hover__background-color: darken(@data-grid-filters-current-action-remove__background-color, 10%); +@data-grid-filters-current-action-remove__size: 1.6rem; + +// +// Filter action & search +// --------------------------------------------- + +.data-grid-filters-actions-wrap { + float: right; +} + +// Data Grid Search +.data-grid-search-control-wrap { + display: none; + float: left; + max-width: 45.5rem; + position: relative; + width: 50%; + :-ms-input-placeholder { + font-style: italic; + } + ::-webkit-input-placeholder { + font-style: italic; + } + ::-moz-placeholder { + font-style: italic; + } + // Submit/search icon + .action-submit { + .action-reset(); + padding: .6rem 2rem .2rem; + position: absolute; + right: 0; + top: 1px; + &:active { + .scale(); + } + &:hover { + &:before { + color: darken(@text__color, 10%); + } + } + &:focus { + box-shadow: @focus__box-shadow; + } + &:before { + &:extend(.abs-icon all); + content: @icon-search__content; + font-size: @data-grid-search-action__size; + transition: @smooth__color; + } + > span { + .hidden(); + } + } + .action-menu { + z-index: 1; + } +} + +.data-grid-search-control { + padding-right: @data-grid-search-action__size + 2rem * 2; + width: 100%; +} + +// Action +.data-grid-filters-action-wrap { + float: left; + padding-left: @indent__base; + .action-default { + font-size: @data-grid-filters__font-size; + padding-left: @data-grid-filters-action__padding-left; + padding-right: @data-grid-filters-action__padding-right; + padding-top: @action__padding-top + .1rem; + &._active { + background-color: @data-grid-filters__background-color; + border-bottom-color: @data-grid-filters__background-color; + border-right-color: @data-grid-filters-action__active__border-color; + font-weight: @font-weight__semibold; + margin-left: 0; + margin-right: 0; + margin-top: -.1rem; + padding-bottom: 1.9rem; + padding-top: @action__padding-top + .2rem; + position: relative; + z-index: 4; + &:after { + background-color: @data-grid-filters-action__active__color; + bottom: 100%; + content: ''; + height: 3px; + left: -1px; + position: absolute; + right: -1px; + } + } + &:before { + &:extend(.abs-icon all); + content: @icon-filter__content; + font-size: 1.8rem; + margin-right: .4rem; + position: relative; + top: -1px; + vertical-align: top; + } + } +} + +// +// Filters content +// --------------------------------------------- + +.admin__data-grid-filters-wrap { + .appearing__off(); + clear: both; + font-size: @data-grid-filters__font-size; + max-height: 0; + transition: opacity .3s ease, padding .3s ease; + &._show { + .appearing__on(); + border-bottom: 1px solid @data-grid-filters-action__active__border-color; + border-top: 1px solid @data-grid-filters-action__active__border-color; + margin-bottom: .7rem; + max-height: 50rem; + padding: 3.6rem 0 3rem; + position: relative; + top: -1px; + z-index: 3; + .admin__data-grid-filters-footer, + .admin__data-grid-filters { + display: block; + } + } + // Field labels + .admin__form-field-legend, + .admin__form-field-label { + display: block; + font-weight: bold; + margin: 0 0 .3rem; + text-align: left; + } + // First level field + .admin__form-field { + float: left; + margin-bottom: 2em; + margin-left: 0; + padding-left: @data-grid-filters-fieldset__inner-side / 2; + padding-right: @data-grid-filters-fieldset__inner-side / 2; + width: 100% / @data-grid-filters-fieldset__columns; + &:nth-child(5n + 1) { + clear: both; + } + // Inner fields + .admin__form-field { + float: none; + margin-bottom: 1.5rem; + padding-left: 0; + padding-right: 0; + width: auto; + &:last-child { + margin-bottom: 0; + } + // Inner field labels + .admin__form-field-label { + border: @field-control__border-width solid transparent; + float: left; + font-weight: normal; + line-height: @field-control__line-height; + margin-bottom: 0; + padding-bottom: @field-control__padding-bottom; + padding-right: 1em; + padding-top: @field-control__padding-top; + width: @data-grid-filters-label__width; + } + .admin__form-field-control { + margin-left: @data-grid-filters-label__width; + } + } + } + .admin__form-field-label, + .admin__control-text, + .admin__control-select { + font-size: @data-grid-filters__font-size; + } + .admin__control-select { + padding-top: @action__padding-top - .1rem; + height: @action__height - .1rem; + } + // Date control + .admin__control-text.hasDatepicker, + .admin__control-select { + width: 100%; + } +} + +// Filters content wrap +.admin__data-grid-filters { + &:extend(.abs-clearfix all); + display: none; + margin-left: -(@data-grid-filters-fieldset__inner-side / 2); + margin-right: -(@data-grid-filters-fieldset__inner-side / 2); +} + +.admin__filters-legend { + .hidden(); +} + +// Filters footer +.admin__data-grid-filters-footer { + &:extend(.abs-clearfix all); + display: none; + font-size: @font-size__base; + .admin__footer-main-actions { + margin-left: 25%; + text-align: right; + } + .admin__footer-secondary-actions { + float: left; + width: 50%; + } +} + +// +// Chips +// --------------------------------------------- + +// Current chips +.admin__data-grid-filters-current { + border-bottom: 1px solid @data-grid-filters-action__active__border-color; + border-top: 1px solid @data-grid-filters-action__active__border-color; + display: none; + font-size: @data-grid-filters__font-size; + margin-bottom: .9rem; + padding-bottom: .8rem; + padding-top: 1.1rem; + width: 100%; + &._show { + display: table; + } +} + +.admin__current-filters-list-wrap, +.admin__current-filters-title-wrap { + display: table-cell; + vertical-align: top; +} + +.admin__current-filters-title { + margin-right: 1em; + white-space: nowrap; +} + +.admin__current-filters-list-wrap { + width: 100%; +} + +.admin__current-filters-list { + margin-bottom: 0; + > li { + display: inline-block; + font-weight: @font-weight__semibold; + margin: 0 1rem .5rem; + padding-right: @data-grid-filters-current-action-remove__size + 1rem; + position: relative; + } + .action-remove { + .action-reset(); + line-height: 1; + position: absolute; + right: 0; + top: 1px; + &:hover { + &:before { + color: @data-grid-filters-current-action-remove__hover__background-color; + } + } + &:active { + .scale(); + } + &:before { + &:extend(.abs-icon all); + color: @data-grid-filters-current-action-remove__background-color; + content: @icon-remove-small__content; + font-size: @data-grid-filters-current-action-remove__size; + transition: @smooth__color; + } + > span { + .hidden(); + } + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-pager.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-pager.less new file mode 100644 index 0000000000000000000000000000000000000000..a30087cb5a6972ca99f7636d3a4fe26e9ee59219 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-pager.less @@ -0,0 +1,63 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// UI -> Data Grid -> Header -> Pager +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@data-grid-pager-action__width: 4.4rem; + +// + +.admin__data-grid-pager-wrap { + text-align: right; +} + +.admin__data-grid-pager { + display: inline-block; + margin-left: @content__indent; + .admin__control-text::-webkit-outer-spin-button, + .admin__control-text::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + .admin__control-text { + -moz-appearance: textfield; + text-align: center; + width: @data-grid-pager-action__width; + } +} + +.action-previous, +.action-next { + width: @data-grid-pager-action__width; + &:before { + &:extend(.abs-icon all); + font-weight: @font-weight__bold; + } + > span { + .hidden(); + } +} + +.action-previous { + margin-right: 2.5rem; + text-indent: -.25em; + &:before { + content: @icon-caret-left__content; + } +} + +.action-next { + margin-left: 1.5rem; + text-indent: .1em; + &:before { + content: @icon-caret-right__content; + } +} diff --git a/app/design/adminhtml/Magento/backend/composer.json b/app/design/adminhtml/Magento/backend/composer.json index 8ae2687dac7e5d03b2248d8dff711c8d8fd8a1c9..a0fc76610568403a31ae8e6e3184977f90c6cce9 100644 --- a/app/design/adminhtml/Magento/backend/composer.json +++ b/app/design/adminhtml/Magento/backend/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-theme", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_actions.less b/app/design/adminhtml/Magento/backend/web/css/source/_actions.less index 7a3f017a0a5b58b1841e07680b58341e1e00a9f6..0353568d0e94abea48be8579cb2adcf6d3f1dcf9 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_actions.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_actions.less @@ -7,7 +7,10 @@ // Imports // _____________________________________________ +@import 'actions/_actions-dropdown.less'; @import 'actions/_actions-split.less'; +@import 'actions/_actions-select.less'; +@import 'actions/_actions-multiselect.less'; // // Variables @@ -15,12 +18,15 @@ // Base button @button__background-color: @color-gray89; -@button__border-color: @color-gray68; +@button__border-color: @action__border-color; +@button__border-size: 1px; +@button__border-style: solid; @button__color: @color-brownie; @button__font-family: @font-family__base; -@button__font-size: @font-size__base; -@button__padding-top: .5em; -@button__padding-bottom: .57em; +@button__font-size: @action__font-size; +@button__line-height: @action__line-height; +@button__padding-top: @action__padding-top; +@button__padding-bottom: @action__padding-bottom; @button__padding-horizontal: 1em; @button__padding-vertical__l: .6875em; @@ -46,11 +52,18 @@ @button-secondary__active__background-color: @color-very-dark-gray-black2; @button-secondary__hover__background-color: @color-very-dark-gray-black2; +// Triangle marker +@button-marker-triangle__height: .5rem; +@button-marker-triangle__width: .8rem; + +@button-marker-triangle__height__xl: .9rem; +@button-marker-triangle__width__xl: 1.2rem; + // // Utilities // _____________________________________________ -.action-reset () { +.action-reset() { background-color: transparent; border: none; border-radius: 0; @@ -64,6 +77,47 @@ } } +// Used in action dropdown, actions split & all other actions with triangle marker +.action-toggle-triangle ( + @_dropdown__padding-right: 3rem; + @_triangle__height: @button-marker-triangle__height; + @_triangle__width: @button-marker-triangle__width; + @_triangle__color: @color-black; + @_triangle__hover__color: darken(@_triangle__color, 10%); + @_triangle__right: (@_dropdown__padding-right / 2) - (@_triangle__width / 2); +) { + padding-right: @_dropdown__padding-right; + &._active, + &.active { + &:after { + transform: rotate(180deg); + } + } + &:after { + border-color: @_triangle__color transparent transparent transparent; + border-style: solid; + border-width: @_triangle__height @_triangle__width / 2 0 @_triangle__width / 2; + content: ''; + height: 0; + margin-top: -((@_triangle__width / 2) / 2); + position: absolute; + right: @_triangle__right; + top: 50%; + transition: all .2s linear; + width: 0; + ._active &, + .active & { + transform: rotate(180deg); + } + } + &:hover { + &:after { + border-color: @_triangle__hover__color transparent transparent transparent; + } + } +} + + // // Extends // _____________________________________________ @@ -73,15 +127,16 @@ } .abs-action-pattern { - border: 1px solid; + border: @button__border-size @button__border-style; border-radius: 0; // ToDo UI: Delete with admin scope display: inline-block; font-family: @button__font-family; font-size: @button__font-size; font-weight: @font-weight__semibold; + line-height: @button__line-height; padding: @button__padding-top @button__padding-horizontal @button__padding-bottom; text-align: center; - vertical-align: baseline; // ToDo UI: Delete with admin scope + vertical-align: baseline; &[disabled], &.disabled { cursor: default; @@ -97,6 +152,29 @@ padding-top: @button__padding-vertical__l; } +.abs-action-delete { + &:extend(.abs-action-reset all); + &:extend(.abs-icon all); + display: inline-block; + font-size: 1.6rem; + margin-left: 1.2rem; + padding-top: .7rem; + text-decoration: none; + vertical-align: middle; + &:after { + color: @color-very-dark-gray; + content: @icon-delete__content; + } + &:hover { + &:after { + color: @color-very-dark-gray-black2; + } + } + > span { + &:extend(.abs-visually-hidden all); + } +} + .abs-action-default { .action-default(); } @@ -117,6 +195,10 @@ .action-quaternary(); } +.abs-action-menu { + .action-menu(); +} + // // Default action // --------------------------------------------- @@ -222,6 +304,89 @@ button { } } +// +// Specific actions +// --------------------------------------------- + +.action-close { + > span { + .hidden(); + } + &:extend(.abs-action-reset all); + &:active { + .scale(); + } + &:before { + &:extend(.abs-icon all); + content: @icon-close-mage__content; + .transition(color); + } + &:hover { + cursor: pointer; + text-decoration: none; + } +} + +// +// Action menu +// --------------------------------------------- + +// Used in actions split, action select and all other simple (one line) action menu list +.action-menu { + .appearing__off(); + background-color: @page-wrapper__background-color; + border: 1px solid @action__active__border-color; + border-radius: 1px; + box-shadow: @component__box-shadow__base; + color: @text__color; + display: block; // ToDo UI: Should be deleted with old styles + font-weight: @font-weight__regular; + left: 0; + list-style: none; + margin: 2px 0 0; // Action box-shadow + 1px indent + min-width: 0; // ToDo UI: Should be deleted with old styles + padding: 0; + position: absolute; + right: 0; + top: 100%; + transition: opacity @appearing__transition-duration @apperaing__transition-timing-function; + &._active { + .appearing__on(); + } + > li { + display: block; + border: none; // ToDo UI: Should be deleted with old styles + padding: 0; + transition: background-color .1s linear; + > a { + &:hover { + text-decoration: none; + } + } + &:hover { + background-color: @action-menu__hover__background-color; + } + &:active { + background-color: darken(@action-menu__hover__background-color, 10%); + } + } + .item, + .action-menu-item { + display: block; + padding: .6875em 1em; + cursor: pointer; + } + a { + &.action-menu-item { + color: @text__color; + &:focus { + background-color: @action-menu__hover__background-color; + box-shadow: none; + } + } + } +} + // // ToDo UI: Button migration // _____________________________________________ diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_classes.less b/app/design/adminhtml/Magento/backend/web/css/source/_classes.less new file mode 100644 index 0000000000000000000000000000000000000000..2b420d0e88ff98160f00b6af5ae2953665a61568 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/_classes.less @@ -0,0 +1,16 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Helper cross js and styles classes +// _____________________________________________ + +// Can be used for disabled elements, equal disabled='disabled' attribute +._disabled { + .disabled(); + &:hover { + .disabled(); + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_forms.less b/app/design/adminhtml/Magento/backend/web/css/source/_forms.less index 131ae92ae03dee1b4e619d4a5939357de56fa86b..624092c1068bb181bf7e9e60329e41e13c0f4f8a 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_forms.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_forms.less @@ -7,4 +7,4 @@ @import 'forms/_fields.less'; @import 'forms/_tooltip.less'; @import 'forms/_temp.less'; -@import 'forms/_dropdown.less'; +@import 'forms/_checkbox-radio.less'; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_grid.less b/app/design/adminhtml/Magento/backend/web/css/source/_grid.less index f139356abfa2948d91e01fa63dffde477b7067de..4a7856af7947c918231a4d19f46be1f279336daa 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_grid.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_grid.less @@ -65,9 +65,8 @@ .row-gutter { margin-left: -(@content__indent / 2); margin-right: -(@content__indent / 2); - .col-gutter { + > [class*='col-'] { padding-left: @content__indent / 2; padding-right: @content__indent / 2; } } - diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_sources.less b/app/design/adminhtml/Magento/backend/web/css/source/_sources.less index 82de6e8fd0d1b023a6739df8b85ab07b820f1724..197d0d89a271cb453c4048d7a02099dbd23ba63b 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_sources.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_sources.less @@ -11,8 +11,8 @@ @import '_utilities.less'; @import '_reset.less'; @import '_typography.less'; -@import '_icons.less'; @import '_lists.less'; +@import '_icons.less'; @import '_forms.less'; @import '_actions.less'; @import '_tables.less'; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_structure.less b/app/design/adminhtml/Magento/backend/web/css/source/_structure.less index f971e04756ee517f8ded56eaf5346c5cf1726c81..f7e0dbde07ca8958b2778f02d9811eb077738ae8 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_structure.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_structure.less @@ -29,6 +29,7 @@ body { .page-wrapper { background-color: @page-wrapper__background-color; + min-width: 102.4rem; padding-left: @page-wrapper__indent-left; } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_tables.less b/app/design/adminhtml/Magento/backend/web/css/source/_tables.less index bf591fe9921f70066c979e51f23d908baf851669..c72dda688951972b6e6b5b74851f0c8355c12727 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_tables.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_tables.less @@ -16,29 +16,48 @@ @table-tfoot__background-color: @color-white-fog; -@table-info__font-size: 1.3rem; -@table-info__padding-vertical: 1rem; -@table-info__padding-horizontal: 1.5rem; +@admin__table-primary__font-size: 1.3rem; +@admin__table-primary__padding-vertical: 1rem; +@admin__table-primary__padding-horizontal: 1.5rem; + +@admin__table-secondary__padding-vertical: @admin__table-primary__padding-vertical; +@admin__table-secondary__padding-horizontal: 1rem; +@admin__table-secondary-caption__font-size: 1.8rem; +@admin__table-secondary-cell__odd__color: @color-white-fog2; +@admin__table-secondary-th__color: @color-brownie-light; // // Tables // _____________________________________________ -// -// Utilities -// --------------------------------------------- +table { + background-color: transparent; + color: @table__color; + > caption { + margin-bottom: .5em; + } +} + +.admin__table-primary, +.admin__table-secondary { + width: 100%; +} -.table-info { - font-size: @table-info__font-size; +.admin__table-primary { + font-size: @admin__table-primary__font-size; th, td { - padding: @table-info__padding-vertical @table-info__padding-horizontal; + padding: @admin__table-primary__padding-vertical @admin__table-primary__padding-horizontal; text-align: left; + &:first-child { + padding-left: 0; + } } th { border-bottom: 1px solid @table-th__border-color; border-top: 1px solid @table-th__border-color; font-weight: @font-weight__bold; + vertical-align: bottom; } td { border-bottom: 1px solid @table-td__border-color; @@ -55,15 +74,59 @@ } tfoot { background: @table-tfoot__background-color; + font-weight: @font-weight__semibold; + th, + td { + &:first-child { + padding-left: @admin__table-primary__padding-horizontal; + } + } } } -// - -table { - background-color: transparent; - color: @table__color; - > caption { - margin-bottom: .5em; +.admin__table-secondary { + caption { + font-size: @admin__table-secondary-caption__font-size; + font-weight: @font-weight__bold; + margin-bottom: .75em; + text-align: left; + } + tbody { + th { + vertical-align: top; + } + } + tr { + &:nth-child(odd) { + th, + td { + background-color: @admin__table-secondary-cell__odd__color; + } + } + } + th, + td { + padding: @admin__table-secondary__padding-horizontal @admin__table-secondary__padding-vertical; + text-align: left; + } + th { + color: @admin__table-secondary-th__color; + font-weight: @font-weight__regular; + } + tfoot { + tr { + &:nth-child(odd) { + th, + td { + background-color: @color-white; + } + } + &:first-child { + border-top: 1px solid @table-td__border-color; + } + } + } + .admin__total-amount { + text-align: right; } } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less b/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less index fa113a59c52acb0e46b2968e09eab6d0c9f33f49..1728f1f08b5e655e4f61a43b9efd443f266c5c5e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less @@ -57,7 +57,6 @@ // Tabs content .ui-tabs-panel { - border-top: 1px solid @color-gray68; margin-top: -1px; padding: 2rem; } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_typography.less b/app/design/adminhtml/Magento/backend/web/css/source/_typography.less index 476415b15756aca49c23ba1c8218a3cc679666a6..ef2beb554b5a79d5a0512720366d68cc6787b81b 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_typography.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_typography.less @@ -3,6 +3,19 @@ // * See COPYING.txt for license details. // */ +// +// Utilities +// --------------------------------------------- + +.link-pattern() { + color: @link__color; + text-decoration: none; + &:hover { + color: @link__hover__color; + text-decoration: underline; + } +} + .font-face( @family-name: @font-family-name__base, @font-path: '@{baseDir}fonts/opensans/light/opensans-300', @@ -31,6 +44,8 @@ @font-style: normal ); +// + html, body { height: 100%; @@ -109,10 +124,5 @@ small { // Links a { - color: @link__color; - text-decoration: none; - &:hover { - color: @link__hover__color; - text-decoration: underline; - } + .link-pattern(); } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_utilities.less b/app/design/adminhtml/Magento/backend/web/css/source/_utilities.less index 5182c77ed22e5463c2e377a7d09b17f0a12f3820..84a014a902f9bdc18a9e1f99330fc50891985d80 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_utilities.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_utilities.less @@ -7,3 +7,32 @@ @import 'utilities/_grid.less'; @import 'utilities/_animations.less'; @import 'utilities/_spinner.less'; + +.hidden() { + clip: rect(0, 0, 0, 0); + overflow: hidden; + position: absolute; +} + +.disabled() { + box-shadow: none; + cursor: default; + opacity: .5; + outline: 0; +} + +.text-overflow-ellipsis() { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.appearing__off() { + opacity: 0; + visibility: hidden; +} + +.appearing__on() { + opacity: 1; + visibility: visible; +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_variables.less b/app/design/adminhtml/Magento/backend/web/css/source/_variables.less index a18ebc40b4799ca255df30f31ef303b596f8665c..191918c389c231300ce085f212628874acc1bc6d 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_variables.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_variables.less @@ -10,6 +10,7 @@ @import 'variables/_colors.less'; @import 'variables/_typography.less'; @import 'variables/_icons.less'; +@import 'variables/_actions.less'; @import 'variables/_forms.less'; @import 'variables/_structure.less'; @import 'variables/_animations.less'; \ No newline at end of file diff --git a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-dropdown.less b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-dropdown.less new file mode 100644 index 0000000000000000000000000000000000000000..6f89fefaf392a88cc9042ddb7d1070e5fb3dfc09 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-dropdown.less @@ -0,0 +1,164 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Forms -> Dropdown element +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@action-dropdown__color: @text__color; +@action-dropdown__background-color: @page-wrapper__background-color; +@action-dropdown__border-color: @color-light-gray; +@action-dropdown__font-size: round(@font-size__base - .1rem, 1); +@action-dropdown__height: @action__height; +@action-dropdown__padding-top: .7rem; +@action-dropdown__padding-bottom: .8rem; +@action-dropdown__padding-horizontal: 1.5rem; +@action-dropdown__padding-right: @action-dropdown__padding-horizontal + @action-dropdown-menu__padding-horizontal + @button-marker-triangle__width; +@action-dropdown__active__border-color: @color-blue-pure; +@action-dropdown__hover__color: darken(@action-dropdown__color, 20%); + +@action-dropdown-menu__padding-vertical: .5rem; +@action-dropdown-menu__padding-horizontal: 1rem; + +@action-dropdown-menu-link__padding-vertical: .6rem; +@action-dropdown-menu-link__padding-horizontal: @action-dropdown__padding-horizontal - @action-dropdown-menu__padding-horizontal; + +// +// Utilities +// --------------------------------------------- + +.admin__action-dropdown-menu__align( + @_align +) when (@_align = left) { + .admin__action-dropdown-text { + &:after { + left: -(@component__shadow-size__base + 1); + right: 0; + } + } + .admin__action-dropdown-menu { + left: auto; + right: 0; + } +} + +.admin__action-dropdown-menu__align( + @_align +) when (@_align = right) { + .admin__action-dropdown-text { + &:after { + right: -(@component__shadow-size__base + 1); + left: 0; + } + } + .admin__action-dropdown-menu { + left: 0; + right: auto; + } +} + +.action-dropdown-menu-link-pattern() { + color: @action-dropdown__color; + display: block; + text-decoration: none; +} + +// + +.admin__action-dropdown-wrap { + .admin__action-dropdown-menu__align(left); + display: inline-block; + position: relative; + &.active, + &._active { + .admin__action-dropdown { + border-color: @action-dropdown__active__border-color; + box-shadow: @component__box-shadow__base; + } + // Dropdown helper to prevent box shadow unnecessary appearing + .admin__action-dropdown-text { + &:after { + background-color: @action-dropdown__background-color; + content: ''; + height: @component__shadow-size__base + 1; + position: absolute; + top: 100%; + } + } + .admin__action-dropdown-menu { + .appearing__on(); + } + } + &._disabled { + .admin__action-dropdown { + cursor: default; + } + &:hover { + .admin__action-dropdown { + color: @action-dropdown__color; + } + } + } +} + +.admin__action-dropdown { + .action-toggle-triangle( + @_dropdown__padding-right: @action-dropdown__padding-right; + ); + box-shadow: none; + background-color: @action-dropdown__background-color; + border: 1px solid transparent; + border-bottom: none; + border-radius: 0; + color: @action-dropdown__color; + display: inline-block; + font-size: @action-dropdown__font-size; + font-weight: @font-weight__regular; + letter-spacing: -.025em; + padding: @action-dropdown__padding-top @action-dropdown__padding-right @action-dropdown__padding-bottom @action-dropdown__padding-horizontal; + position: relative; + transition: border-color @appearing__transition-duration @apperaing__transition-timing-function; + vertical-align: baseline; + z-index: 2; + &:hover { + color: @action-dropdown__hover__color; + background-color: @action-dropdown__background-color; + text-decoration: none; + } + // Triangle + &:after { + right: @action-dropdown__padding-horizontal; + } + // Icon + &:before { + margin-right: 1rem; + } +} + +.admin__action-dropdown-menu { + .appearing__off(); + background-color: @action-dropdown__background-color; + border: 1px solid @action-dropdown__active__border-color; + box-shadow: @component__box-shadow__base; + line-height: @line-height__base; + margin-top: -1px; + min-width: 120%; + padding: @action-dropdown-menu__padding-vertical @action-dropdown-menu__padding-horizontal; + position: absolute; + top: 100%; + transition: all @appearing__transition-duration @apperaing__transition-timing-function; + z-index: 1; + > li { + display: block; + > a { + .action-dropdown-menu-link-pattern(); + padding: @action-dropdown-menu-link__padding-vertical @action-dropdown-menu-link__padding-horizontal; + } + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-multiselect.less b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-multiselect.less new file mode 100644 index 0000000000000000000000000000000000000000..597a73358d82bb119a8329b8c2d5a435339f1e0d --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-multiselect.less @@ -0,0 +1,84 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Actions -> Actions multiselect +// _____________________________________________ + +// Action multiselect is a combining of checkbox and dropdown elements + +.action-multiselect-wrap { + &:extend(.abs-clearfix all); + display: inline-block; + padding-top: 1px; + position: relative; + height: @control-checkbox-radio__size; + z-index: @action-multiselect__z-index; + &:hover { + .admin__control-checkbox + label:before, + .action-multiselect-toggle { + border-color: @field-control__hover__border-color; + } + } + &._active { + .admin__control-checkbox + label:before, + .action-multiselect-toggle { + border-color: @action__active__border-color; + } + .action-menu { + .appearing__on(); + } + } + &._disabled { + .admin__control-checkbox { + + label { + &:before { + background-color: @control-checkbox-radio__background-color; + } + } + } + .admin__control-checkbox + label:before, + .action-multiselect-toggle { + border-color: @field-control__border-color; + opacity: 1; + } + } + .admin__control-checkbox, + .admin__control-checkbox + label, + .action-multiselect-toggle { + float: left; + } + .action-multiselect-toggle { + .action-toggle-triangle( + @_triangle__height: @button-marker-triangle__height; + @_triangle__width: @button-marker-triangle__width; + ); + border-radius: 0 1px 1px 0; + height: @control-checkbox-radio__size; + margin-left: -1px; + padding: 0; + position: relative; + transition: @smooth__border-color; + width: @control-checkbox-radio__size; + &:focus { + border-color: @action__active__border-color; + } + &:after { + right: .3rem; + } + > span { + .visually-hidden(); + } + } + .action-menu { + left: -(@data-grid-cell__padding-horizontal + @data-grid-cell__border-width + .1rem); + right: auto; + text-align: left; + margin-top: 1px; + } + .action-menu-item { + white-space: nowrap; + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-select.less b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-select.less new file mode 100644 index 0000000000000000000000000000000000000000..496f6269e8b3ddff1ae01efaf405ea41e37aa979 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-select.less @@ -0,0 +1,64 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Actions -> Action select +// _____________________________________________ + +// Action select have the same visual styles and functionality as native <select> +.action-select-wrap { + @_action-select__border-color: @button__border-color; + @_action-select__active__border-color: @action__active__border-color; + @_action-select-toggle__size: @action__height; + + display: inline-block; + position: relative; + .action-select { + .action-toggle-triangle( + @_dropdown__padding-right: @_action-select-toggle__size; + @_triangle__height: @button-marker-triangle__height; + @_triangle__width: @button-marker-triangle__width; + ); + .text-overflow-ellipsis(); + background-color: @color-white; + font-weight: @font-weight__regular; + text-align: left; + &:hover { + border-color: @field-control__hover__border-color; + &:before { + border-color: @field-control__hover__border-color; + } + } + // Toggle action + &:before { + background-color: @button__background-color; + border: @button__border-size @button__border-style @_action-select__border-color; + bottom: 0; + content: ''; + position: absolute; + right: 0; + top: 0; + width: @_action-select-toggle__size; + } + &._active { + border-color: @_action-select__active__border-color; + &:before { + border-color: @_action-select__active__border-color; + border-left-color: @_action-select__border-color; + } + } + } + &._active { + .action-select { + border-color: @field-control__active__border-color; + &:before { + border-color: @field-control__active__border-color; + } + &:after { + transform: rotate(180deg); + } + } + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less index 050e9bf71fbfc21c19218280971f16cf0169695f..402bd4b223727a8e437a3ce7dd66a6f09c898885 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less @@ -7,15 +7,42 @@ // Actions -> Actions split // _____________________________________________ +// Actions split is a button aggregator with dropdown element + +// +// Extends +// --------------------------------------------- + +.abs-actions-split-xl { + @_dropdown__padding-right: 4rem; + @_action-toggle__width: @_dropdown__padding-right; + + @_triangle__height: @button-marker-triangle__height__xl; + @_triangle__right: (@_dropdown__padding-right / 2) - (@_triangle__width / 2); + @_triangle__width: @button-marker-triangle__width__xl; + + .action-default { + margin-right: @_action-toggle__width; + } + .action-toggle { + padding-right: @_dropdown__padding-right; + &:after { + border-width: @_triangle__height @_triangle__width / 2 0 @_triangle__width / 2; + margin-top: -((@_triangle__width / 2) / 2); + right: @_triangle__right; + } + } +} + +// Double button action .actions-split { @_action-split__min-width: @_action-toggle__width + @_action-default__min-width; - @_action-split-dropdown__hover__background-color: @color-gray89; @_action-default__min-width: 9.3rem; - @_action-toggle__width: 4rem; + @_action-toggle__width: @action__height; .extend__clearfix(); position: relative; - z-index: @split-button__z-index; + z-index: @actions-split__z-index; &.active, &._active, &:hover { @@ -31,8 +58,7 @@ } } .dropdown-menu { - opacity: 1; - visibility: visible; + .appearing__on(); } } .action-toggle, @@ -50,10 +76,10 @@ min-width: @_action-default__min-width; } .action-toggle { - .dropdown-triangle( + .action-toggle-triangle( @_dropdown__padding-right: @_action-toggle__width; - @_triangle__height: .9rem; - @_triangle__width: 1.2rem; + @_triangle__height: @button-marker-triangle__height; + @_triangle__width: @button-marker-triangle__width; ); border-left-color: rgba(0, 0, 0, .2); bottom: 0; @@ -61,13 +87,13 @@ position: absolute; right: 0; top: 0; - // Disable triangle rotation - &._active, - &.active { - &:after { - transform: none; - } - } + // Disable triangle rotation + // &._active, + // &.active { + // &:after { + // transform: none; + // } + // } &.action-secondary, &.secondary, &.action-primary, @@ -77,36 +103,11 @@ } } > span { - .visually-hidden(); + .hidden(); } } - .dropdown-menu { - background-color: @page-wrapper__background-color; - border: 1px solid @button__hover__border-color; - border-radius: 1px; - box-shadow: @component__box-shadow__base; - display: block; // ToDo UI: Should be deleted with old styles - left: 0; - list-style: none; - margin: 2px 0 0; // Action box-shadow + 1px indent - min-width: 0; // ToDo UI: Should be deleted with old styles - opacity: 0; - padding: 0; - position: absolute; - right: 0; - top: 100%; - transition: opacity @appering__transition-duration @apperaing__transition-timing-function; - visibility: hidden; - > li { - border: none; // ToDo UI: Should be deleted with old styles - padding: .6875em; - &:hover { - background-color: @_action-split-dropdown__hover__background-color; - cursor: pointer; - } - &:active { - background-color: darken(@_action-split-dropdown__hover__background-color, 10%); - } - } + .dropdown-menu, + .action-menu { + &:extend(.abs-action-menu all); } } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_calendar-temp.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_calendar-temp.less index 5e59707575f588a5996565b8c7931c0efc2ae9e4..621b01524dceea3fea33932b967c26b0dabf851b 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_calendar-temp.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_calendar-temp.less @@ -16,32 +16,35 @@ @ui-datepicker__border: 1px solid #007dbd; @ui-datepicker__indent: 3px; @ui-datepicker__padding: 20px; -@ui-datepicker__shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.3); +@ui-datepicker__shadow: @component__box-shadow__base; // // Datepicker control // --------------------------------------------- -.admin__control-text.hasDatepicker { - width: 15rem; -} - .admin__control-text { + &.hasDatepicker { + width: 15rem; + } + .ui-datepicker-trigger { .button-reset(); .icon-font( - @icon-calendar, - @_icon-font-size: 3.8rem, - @_icon-font-line-height: 33px, + @_icon-font-content: @icon-calendar__content, + @_icon-font: @icons-admin__font-name, + @_icon-font-size: 2.1rem, + @_icon-font-line-height: @action__height, @_icon-font-text-hide: true, @_icon-font-position: after, @_icon-font-color: @ui-datepicker-icon__color ); - height: 3.3rem; + height: @action__height; overflow: hidden; vertical-align: top; - margin-left: -4rem; + margin-left: -@action__height; display: inline-block; + &:active { + .scale(.975); + } } } @@ -52,6 +55,7 @@ .ui-datepicker { box-sizing: border-box; display: none; + opacity: @component-modal__opacity; padding: @ui-datepicker__padding + @ui-datepicker__indent @ui-datepicker__padding; width: auto; z-index: 999999 !important; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_data-grid-temp.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_data-grid-temp.less index 7098e076357d147d068e180c487cf75a98da5530..2dded4e6efea6ea68ca2f2f0b9474c187b94d7c0 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_data-grid-temp.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_data-grid-temp.less @@ -42,6 +42,9 @@ // --------------------------------------------- .grid { + .hor-scroll { + overflow-x: auto; + } table { &:not(.data-table) { border: none; @@ -111,7 +114,7 @@ border: @data-grid-temp-cell__border-width @data-grid-temp-th__border-style @data-grid-temp-th__border-color; color: @data-grid-temp-th__color; font-weight: @font-weight__semibold; - padding: @data-grid-temp-cell__padding-vertical @data-grid-temp-cell__padding-horizontal;; + padding: @data-grid-temp-cell__padding-vertical @data-grid-temp-cell__padding-horizontal; text-align: left; &:first-child { border-left-color: @data-grid-temp-th__border-color; @@ -184,6 +187,9 @@ margin-left: .5rem; width: 3.5rem; } + &:after { + display: none; + } } } } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_popups.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_popups.less index abac708dc0eb592a27fde7f4d2ca8e198ab276fa..b6d5c27d02ce0a54374c1c8cfed44aa9b979dbcc 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_popups.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_popups.less @@ -26,23 +26,23 @@ @popup-overlay__background-color: rgba(0, 0, 0, .35); +@popup-fieldset__margin-left: 34%; + // // Jquery UI popup window // _____________________________________________ .ui-dialog { + .appearing__off(); background: @popup__background-color; min-width: 40%; - opacity: 0; transform: scale(0.7); transition: all 0.3s; - visibility: hidden; width: 75%; &.ui-dialog-active { + .appearing__on(); transform: scale(1); - opacity: 1; - visibility: visible; } &.ui-draggable { @@ -322,14 +322,13 @@ > .admin__legend { float: none; font-size: 1.8rem; - margin: 0 0 2rem 34%; + margin: 0 0 @indent__base @popup-fieldset__margin-left; width: auto; } - } - .gift_options-popup { - .admin__fieldset { - > .admin__legend { - margin-left: 0; + .product-options { + margin-left: @popup-fieldset__margin-left; + .admin__field-control { + margin-bottom: @indent__base; } } } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_tooltip-temp.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_tooltip-temp.less deleted file mode 100644 index 94e7125551a0a7cc3c696a2c5e618a7d052ef4fb..0000000000000000000000000000000000000000 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_tooltip-temp.less +++ /dev/null @@ -1,78 +0,0 @@ -// /** -// * Copyright © 2015 Magento. All rights reserved. -// * See COPYING.txt for license details. -// */ - -// -// Main elements -> Tooltip -// _____________________________________________ - -// ToDo UI: Consist old styles, should be changed with new design - -//.tooltip { -// display: inline-block; -// margin-left: 5px; -// .help span, -// .help a { -// position: relative; -// z-index: 2; -// width: 22px; -// height: 22px; -// display: inline-block; -// vertical-align: middle; -// cursor: pointer; -// &:before { -// content: "?"; -// font-weight: 500; -// font-size: 18px; -// display: inline-block; -// overflow: hidden; -// height: 22px; -// border-radius: 11px; -// line-height: 22px; -// width: 22px; -// text-align: center; -// color: #ffffff; -// background-color: #514943; -// } -// span { -// .visually-hidden(); -// } -// } -// // TODO Tooltips -// .tooltip-content { -// display: none; -// position: absolute; -// max-width: 200px; -// margin-top: 10px; -// margin-left: -19px; -// padding: 4px 8px; -// border-radius: 3px; -// background: #000; -// background: rgba(49, 48, 43, .8); -// color: #fff; -// text-shadow: none; -// z-index: 20; -// &:before { -// content: ''; -// position: absolute; -// width: 0; -// height: 0; -// top: -5px; -// left: 20px; -// border-left: 5px solid transparent; -// border-right: 5px solid transparent; -// border-bottom: 5px solid #000; -// opacity: .8; -// } -// &.loading { -// position: absolute; -// &:before { -// border-bottom-color: rgba(0, 0, 0, .3); -// } -// } -// } -// &:hover > .tooltip-content { -// display: block; -// } -//} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_checkbox-radio.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_checkbox-radio.less new file mode 100644 index 0000000000000000000000000000000000000000..4ce5832e7c6e9ac8e913303c2d9008f4e8b3c7cb --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_checkbox-radio.less @@ -0,0 +1,173 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@control-checkbox-radio__size: 1.6rem; +@control-checkbox-radio__background-color: @color-white; +@control-checkbox-radio-mark__color: @color-brownie; + +// Checkbox & radio +.admin__control-radio, +.admin__control-checkbox { + cursor: pointer; + opacity: 0.01; // hack for successful selenium tests + overflow: hidden; + position: absolute; + vertical-align: top; + &:after { // ToDo UI: Should be deleted with old styles that generate styles for this element + display: none; + } + + label { + cursor: pointer; + display: inline-block; + &:before { + &:extend(.abs-icon all); + background-color: @control-checkbox-radio__background-color; + border: 1px solid @field-control__border-color; + color: transparent; + float: left; + height: @control-checkbox-radio__size; + text-align: center; + vertical-align: top; + width: @control-checkbox-radio__size; + } + } + // Label with text content + + .admin__field-label { + padding-left: @control-checkbox-radio__size + @field-label__indent; + &:before { + margin: 1px @field-label__indent 0 -(@control-checkbox-radio__size + @field-label__indent); + } + } + // Checked state + &:checked { + + label { + &:before { + color: @control-checkbox-radio-mark__color; + } + } + } + // Disabled state + &.disabled, + &[disabled] { + + label { + cursor: default; + &:before { + background-color: @field-control__disabled__background-color; + border-color: @field-control__border-color; + cursor: default; + } + color: @field-control__color; + opacity: .5; + } + } + &:not([disabled]), + &:not(.disabled) { + // Focus state + &:focus { + + label { + &:before { + ._keyfocus & { + border-color: @field-control__focus__border-color; + } + } + } + } + // Hover state + &:hover { + + label { + &:before { + border-color: @field-control__hover__border-color; + } + } + } + } +} + +// Radio +.admin__control-radio { + + label { + &:before { + border-radius: @control-checkbox-radio__size; + content: @icon-enable__content; + font-size: 1rem; + transition: @smooth__border-color, color .1s ease-in; + } + } + // Discard extend line-height 1, to fix animation + &.admin__control-radio { + + label { + &:before { + line-height: 140%; + } + } + } + // Radio checked state + &:checked { + &:not([disabled]), + &:not(.disabled) { + // Prevent hover effects for checked radio + &:hover { + cursor: default; + + label { + cursor: default; + &:before { + border-color: @field-control__border-color; + } + } + } + } + } +} + +// Checkbox +.admin__control-checkbox { + + label { + &:before { + border-radius: 1px; + content: ''; + font-size: 0; + transition: font-size .1s ease-out, color .1s ease-out, @smooth__border-color; + } + } + &:checked { + + label { + &:before { + content: @icon-check-mage__content; + font-size: 1.1rem; + line-height: 125%; + } + } + } + &:not(:checked) { + &._indeterminate, + &:indeterminate { + + label { + &:before { + color: @control-checkbox-radio-mark__color; + content: '-'; + font-family: @font-family__base; + font-size: @font-size__base; + font-weight: @font-weight__bold; + } + } + } + } +} + +// +// ToDo UI: Delete with old scope +// --------------------------------------------- + +input[type="checkbox"], +input[type="radio"] { + &.admin__control-checkbox { + position: absolute; + margin: 0; + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_control-table.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_control-table.less index 0a5bda543853f0f2734bcf8fbb3934469ac02eb2..4d4875471506fe522edf4ccb64282899c82a240d 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_control-table.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_control-table.less @@ -52,4 +52,7 @@ } } } + .action-delete { + &:extend(.abs-action-delete all); + } } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_controls.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_controls.less index 6d6619c82ef5dc131ba6596b9cb36cf025615906..3c8edc32869948f9627bc02df3ba11f8db67a89d 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_controls.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_controls.less @@ -11,16 +11,27 @@ // _____________________________________________ @field-control__background-color: @color-white; -@field-control__border-color: @color-gray68; +@field-control__border-color: @action__border-color; +@field-control__border-radius: 1px; +@field-control__border-width: .1rem; @field-control__color: @color-very-dark-gray-black; -@field-control__font-size: 1.4rem; -@field-control__height: 3.3rem; +@field-control__font-size: @action__font-size; +@field-control__line-height: @action__line-height; +@field-control__height: @action__height; +@field-control__padding-top: @action__padding-top; +@field-control__padding-horizontal: 1rem; +@field-control__padding-bottom: @action__padding-bottom; + +@field-control__active__border-color: @field-control__focus__border-color; +@field-control__hover__border-color: @action__hover__border-color; +@field-control__focus__border-color: @color-blue-pure; +@field-control__disabled__background-color: @color-lighter-gray; + @field-control-addon__color: @color-gray52; + @field-control-option-label__padding-left: 26px; -// States -@field-control__disabled__background-color: @color-lighter-gray; -@field-control__focus__border-color: @color-blue-pure; +@field-label__indent: 1rem; @field-label__disabled__color: @color-gray60; @field-label__required__color: @color-phoenix; @@ -32,26 +43,32 @@ // Common // --------------------------------------------- -.__form-control-styles() { +.__form-control-pattern() { background-color: @field-control__background-color; - border-radius: .1rem; - border: 1px solid @field-control__border-color; + border-radius: @field-control__border-radius; + border: @field-control__border-width solid @field-control__border-color; color: @field-control__color; font-size: @field-control__font-size; font-weight: @font-weight__regular; - height: @field-control__height; - max-width: 100%; - padding: 0 1rem; - transition: border-color .1s ease-in; + line-height: @field-control__line-height; + height: auto; + width: auto; + padding: @field-control__padding-top @field-control__padding-horizontal @field-control__padding-bottom; + transition: @smooth__border-color; + vertical-align: baseline; +} + +.__form-control-pattern__hover() { + border-color: @field-control__hover__border-color; } -.__form-control-styles__focus() { +.__form-control-pattern__focus() { border-color: @field-control__focus__border-color; box-shadow: none; outline: 0; } -.__form-control-styles__disabled() { +.__form-control-pattern__disabled() { background-color: @field-control__disabled__background-color; border-color: @field-control__border-color; color: @field-control__color; @@ -61,14 +78,12 @@ // Input text styles .admin__control-text { - .extend__form-control-styles(); - line-height: @field-control__height; - width: 100%; + &:extend(.abs-form-control-pattern all); } // Select styles .admin__control-select { - .extend__form-control-styles(); + &:extend(.abs-form-control-pattern all); .css(appearance, none, 1); background-repeat: no-repeat; @@ -84,7 +99,14 @@ background-position+: ~'calc(100% - 33px)' 0; background-size+: 1px 100%; + height: @field-control__height; padding-right: 4.4rem; // Distance between select switch and inner text + transition: @smooth__border-color; + + &:hover { + border-color: @field-control__hover__border-color; + cursor: pointer; + } &:focus { background-image+: url('../images/arrows-bg.svg'); @@ -95,12 +117,14 @@ background-image+: linear-gradient(@field-control__focus__border-color, @field-control__focus__border-color); background-position+: ~'calc(100% - 33px)' 0; + border-color: @field-control__focus__border-color; } &::-ms-expand { display: none; } .ie9 & { - padding-right: 0; + background-image: none; + padding-right: @field-control__padding-horizontal; } } @@ -115,7 +139,7 @@ option:empty { // Multiple select .admin__control-multiselect { - .extend__form-control-styles(); + &:extend(.abs-form-control-pattern all); height: auto; padding: .6rem 1rem; } @@ -128,20 +152,22 @@ option:empty { z-index: 1; } -.admin__control-file-label:before { - &:extend(.__form-control-styles); - content:''; - left: 0; - position: absolute; - top: 0; - width: 100%; - z-index: 0; - .admin__control-file:active + &, - .admin__control-file:focus + & { - &:extend(.__form-control-styles:focus); - } - .admin__control-file[disabled] + & { - &:extend(.__form-control-styles[disabled]); +.admin__control-file-label { + :before { + &:extend(.abs-form-control-pattern); + content:''; + left: 0; + position: absolute; + top: 0; + width: 100%; + z-index: 0; + .admin__control-file:active + &, + .admin__control-file:focus + & { + &:extend(.abs-form-control-pattern:focus); + } + .admin__control-file[disabled] + & { + &:extend(.abs-form-control-pattern[disabled]); + } } } @@ -153,94 +179,35 @@ option:empty { width: auto; } -// Textarea -.admin__control-textarea { - .extend__form-control-styles(); - height: 8.48rem; - line-height: 1.18; - padding-top: .8rem; - resize: vertical; - width: 100%; -} +// +// Support text. Can be used on label or plain text to align controls & actions +// --------------------------------------------- -// Checkboxes and radios -.admin__control-radio, -.admin__control-checkbox { - cursor: pointer; - margin: .3rem 0 0; - opacity: 0.01; // hack for successful selenium tests - overflow: hidden; - position: absolute; - vertical-align: top; - + label { - cursor: pointer; - display: inline-block; - padding-left: @field-control-option-label__padding-left; - - &:before { - background: @field-control__background-color; - border-radius: .2rem; - border: 1px solid @field-control__border-color; - color: transparent; - content: @icon-check-mage__content; - float: left; - font: 0/14px @icons-admin__font-name; - height: 1.6rem; - margin: 1px 10px 0 -26px; - text-align: center; - transition: border-color .1s ease-in, color .1s ease-in, font-size .1s ease-in; - vertical-align: top; - width: 1.6rem; - } - } - &:focus { - + label { - ._keyfocus & { - &:extend(._keyfocus *:focus); - } - &:before { - border-color: @field-control__focus__border-color; - } - } - } - &[disabled] { - + label { - &:before { - background-color: @field-control__disabled__background-color; - border-color: @field-control__border-color; - } - color: @field-control__color; - opacity: @disabled__opacity; - } - } +.admin__control-support-text { // ToDo UI: should be renamed to .admin__control-text + border: @field-control__border-width solid transparent; + display: inline-block; + font-size: @field-control__font-size; + line-height: @field-control__line-height; + padding-top: @field-control__padding-top; + padding-bottom: @field-control__padding-bottom; } -.admin__control-radio { - + label { - &:before { - border-radius: .8rem; - content: @icon-enable__content; - } - } - &:checked { - + label { - &:before { - color: @color-brownie; - font-size: 1rem; - } - } +[class*='admin__control-'] { + + .admin__control-support-text { + margin-left: .7rem; } } -.admin__control-checkbox { - &:checked { - + label { - &:before { - color: @color-brownie; - font-size: 1.1rem; - } - } - } +// +// Textarea +// --------------------------------------------- + +.admin__control-textarea { + &:extend(.abs-form-control-pattern all); + height: 8.48rem; + line-height: 1.18; + padding-top: .8rem; + resize: vertical; } // Control with additional prefix or suffix label @@ -283,7 +250,7 @@ option:empty { } } & + [class*='admin__addon-']:before { - &:extend(.__form-control-styles); + &:extend(.abs-form-control-pattern); bottom: 0; box-sizing: border-box; content: ''; @@ -294,10 +261,10 @@ option:empty { z-index: 0; } &[disabled] + [class*='admin__addon-']:before { - &:extend(.__form-control-styles[disabled]); + &:extend(.abs-form-control-pattern[disabled]); } &:focus + [class*='admin__addon-']:before { - &:extend(.__form-control-styles:focus); + &:extend(.abs-form-control-pattern:focus); } } } @@ -325,6 +292,7 @@ option:empty { order: 0; } } + .ie9 { .admin__control-addon { &:after { diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_dropdown.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_dropdown.less deleted file mode 100644 index 47fec57d10e088af1bf6aaa03f602f389199accb..0000000000000000000000000000000000000000 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_dropdown.less +++ /dev/null @@ -1,68 +0,0 @@ -// /** -// * Copyright © 2015 Magento. All rights reserved. -// * See COPYING.txt for license details. -// */ - -// -// Forms -> Dropdown element -// _____________________________________________ - -// -// Variables -// --------------------------------------------- - -@dropdown__color: @text__color; - -@dropdown-menu__hover__background-color: @color-blue-clear-sky; -@dropdown-menu__active__background-color: darken(@color-blue-clear-sky, 5%); - -// -// Mixins -// --------------------------------------------- - -.dropdown-triangle ( - @_dropdown__padding-right: 3rem; - @_triangle__width: .8rem; - @_triangle__height: .5rem; - @_triangle__color: @color-black; - @_triangle__hover__color: darken(@_triangle__color, 10%); - @_triangle__right: (@_dropdown__padding-right / 2) - (@_triangle__width / 2); -) { - padding-right: @_dropdown__padding-right; - &._active, - &.active { - &:after { - transform: rotate(180deg); - } - } - &:after { - border-color: @_triangle__color transparent transparent transparent; - border-style: solid; - border-width: @_triangle__height @_triangle__width / 2 0 @_triangle__width / 2; - content: ''; - height: 0; - margin-top: -((@_triangle__width / 2) / 2); - position: absolute; - right: @_triangle__right; - top: 50%; - transition: all .2s linear; - width: 0; - ._active &, - .active & { - transform: rotate(180deg); - } - } - &:hover { - &:after { - border-color: @_triangle__hover__color transparent transparent transparent; - } - } -} - -// - -.admin__action-dropdown { - .action-reset(); - .dropdown-triangle(); - color: @dropdown__color; -} \ No newline at end of file diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_extends.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_extends.less index 699c2ba354eeb9fdf97406c9211242490823a08a..0a883946949c2fa22cdbdd52c5fd05a6a6d46934 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_extends.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_extends.less @@ -7,23 +7,16 @@ // Extend common form control styles // --------------------------------------------- -.extend__form-control-styles() { - &:extend(.__form-control-styles); - &:focus { - &:extend(.__form-control-styles:focus); - } - &[disabled] { - &:extend(.__form-control-styles[disabled]); +.abs-form-control-pattern { + .__form-control-pattern(); + &:hover { + .__form-control-pattern__hover(); } -} - -.__form-control-styles { - .__form-control-styles(); &:focus { - .__form-control-styles__focus(); + .__form-control-pattern__focus(); } &[disabled] { - .__form-control-styles__disabled(); + .__form-control-pattern__disabled(); } } @@ -34,6 +27,7 @@ .extend__field-rows() { &:extend(.abs-field-rows all); } + .abs-field-rows[class] { > .admin__field-control { float: none; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less index f5ae9614e8a91894ab3da0d2197abc17a2893db9..def207f2a0bb7dab63a8eca3eab4cfd38b2e9652 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less @@ -28,13 +28,15 @@ // Form Fields // _____________________________________________ +// // Fieldset +// --------------------------------------------- + .admin__fieldset { border: 0; margin: 0; min-width: 0; padding: 0; - > .admin__field { border: 0; margin: 0; @@ -54,7 +56,24 @@ } } +.admin__form-field { + border: 0; + margin: 0; + padding: 0; +} + +.admin__form-field-control, +.admin__field-control { + .admin__control-text, + .admin__control-textarea { + width: 100%; + } +} + +// // Label +// --------------------------------------------- + .admin__field-label { color: @field-label__color; margin: 0; @@ -64,7 +83,7 @@ display: none; } - [class]:not(.admin__field-option) > & { + .admin__field:not(.admin__field-option) > & { font-family: @font-family__base; font-size: @field-label__font-size; font-weight: @font-weight__semibold; @@ -74,11 +93,10 @@ word-wrap: break-word; &:before { + .appearing__off(); content: '.'; margin-left: -7px; overflow: hidden; - visibility: hidden; - width: 0; } span { @@ -109,7 +127,10 @@ } } +// // Field +// --------------------------------------------- + .admin__field { margin-bottom: 0; @@ -163,13 +184,16 @@ } } } - .admin__field-control { & + & { margin-top: 1.5rem; } } +// +// Field messages +// --------------------------------------------- + // Field error message .admin__field-error { background: @field-error-message__background-color; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_tooltip.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_tooltip.less index dbb52ffa5d3b74aec7574b566ef5ff1e3858536d..67fb5f3926aac1a7e8ee4790987f2a951641a250 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_tooltip.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_tooltip.less @@ -44,24 +44,16 @@ display: block; } .admin__field-tooltip-content { - @_shadow: 0 2px 8px 0 rgba(0, 0, 0, .3); - .css(box-shadow, @_shadow); - background: @field-tooltip-content__background-color; - border-radius: 1px; - border: 1px solid @field-tooltip-content__border-color; + &:extend(.abs-admin__field-tooltip-content all); bottom: 42px; display: none; - padding: 15px 25px; - position: absolute; right: -70px; - width: 320px; - z-index: 1; &:after, &:before { .arrow( - @_position: down, - @_size: 16px, - @_color: @field-tooltip-content__border-color + @_position: down, + @_size: 16px, + @_color: @field-tooltip-content__border-color ); content: ""; display: block; @@ -77,3 +69,15 @@ } } } + +.abs-admin__field-tooltip-content { + @_shadow: 0 2px 8px 0 rgba(0, 0, 0, .3); + .css(box-shadow, @_shadow); + background: @field-tooltip-content__background-color; + border-radius: 1px; + border: 1px solid @field-tooltip-content__border-color; + padding: 15px 25px; + position: absolute; + width: 320px; + z-index: 1; +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_actions.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_actions.less new file mode 100644 index 0000000000000000000000000000000000000000..6cb821a11a68f5e895607cd5a8c21224807ad21f --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_actions.less @@ -0,0 +1,22 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Actions +// _____________________________________________ + +@action__border-color: @color-gray68; +@action__font-size: @font-size__base; +@action__line-height: @line-height__base; +@action__padding-top: round(((@field-control__height - @field-control__font-size * @field-control__line-height - @field-control__border-width * 2) / 2), 1); +@action__padding-bottom: @field-control__padding-top; +@action__height: 3.3rem; + +@action__active__border-color: @color-blue-pure; // Not the same as @button__hover__border-color +@action__hover__background-color: @color-blue-clear-sky; +@action__hover__border-color: darken(@action__border-color, 15%); + +// Actions menu +@action-menu__hover__background-color: @color-gray89; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_animations.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_animations.less index 1284a440a9e5229d53ec39b228c23ea3d3f15d64..986647aefd2700ca241759e9b6b238288270a7b9 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_animations.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_animations.less @@ -7,5 +7,9 @@ // Transitions // _____________________________________________ -@appering__transition-duration: .15s; +@appearing__transition-duration: .15s; @apperaing__transition-timing-function: ease; + +@smooth__color: color .1s linear; +@smooth__background-color: background-color .1s linear; +@smooth__border-color: border-color .1s linear; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_colors.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_colors.less index 61823ceffe0be26f3e8d9bea2908fee156846cc2..80492cbd3cd378486cdda5de768ebb8eb4152145 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_colors.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_colors.less @@ -21,6 +21,7 @@ @color-very-dark-gray1: #777; @color-brownie-vanilla: #736963; @color-dark-gray: #808080; +@color-darkie-gray: #8a837f; @color-gray65: #a6a6a6; @color-gray65-almost: #a79d95; @color-gray65-lighten: #aaa6a0; @@ -38,6 +39,7 @@ @color-very-light-gray: #fcfcfc; @color-ivory: #f7f3eb; @color-white-fog2: #f1f1f1; +@color-lazy-sun-white: #fffbe6; @color-lazy-sun: #fffbbb; @color-lazy-sunny: #fff1ad; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less index 2e081b044437fa866129b1d5b83ac9b6e736bf24..65feb808800fdab0b5f6636f193159003226bf11 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less @@ -33,8 +33,12 @@ @z-index-9: 900; @z-index-10: 1000; +// z-index 2 +@actions-split__z-index: @z-index-2; +@action-multiselect__z-index: @z-index-2; + // z-index 3 -@split-button__z-index: @z-index-3; +@data-grid-header__z-index: @z-index-3; // z-index 4 @header__z-index: @z-index-4; @@ -63,3 +67,5 @@ @component__shadow-size__base: 5px; @component__box-shadow__base: 1px 1px @component__shadow-size__base rgba(0, 0, 0, .5); + +@component-modal__opacity: .98; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_typography.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_typography.less index fa70769896ebb837737830e6ab90f4a4c4ada786..95422456d853c3239a80cf9bdbd14df5bdd0485e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_typography.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_typography.less @@ -17,6 +17,7 @@ @font-size__l: 1.6rem; @font-size__base: 1.4rem; @font-size__s: 1.2rem; +@font-size__tiny: 1.1rem; @font-size__xs: 1rem; @line-height__base: 1.4; diff --git a/app/design/adminhtml/Magento/backend/web/css/styles-old.less b/app/design/adminhtml/Magento/backend/web/css/styles-old.less index f6b0cff9e7c8de6cddad3de71d5e7484d8d2aa14..77fb1698576b0de4f3115cf7906241a6e82e5e9e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/styles-old.less +++ b/app/design/adminhtml/Magento/backend/web/css/styles-old.less @@ -2013,13 +2013,9 @@ input.no-display, } } - .col-2-left-layout, - .col-1-layout { + .col-2-left-layout { margin: 0 auto; position: relative; - } - - .col-2-left-layout { &:before { position: absolute; content: ""; @@ -3167,8 +3163,7 @@ input.no-display, border-radius: 5px; } - .adminhtml-rma-new .order-totals, - .order-comments-history .order-comments-history { + .adminhtml-rma-new .order-totals { float: none; width: 100%; } @@ -3312,40 +3307,6 @@ input.no-display, } } - // - // Order view - // -------------------------------------- - - .order-comments-history fieldset { - border: 0; - margin: 0; - padding: 0; - } - - .order-comments-history textarea, - .rma-history-form textarea { - height: 6em; - margin: 5px 0 10px; - resize: vertical; - width: 100%; - } - - .order-comments-history input[type="checkbox"] { - margin-right: 5px; - } - - .order-history-comments-options { - float: left; - } - - .order-comments-history .actions { - float: right; - } - - [class*="-order-"] .fieldset-wrapper address { - overflow: auto; - } - // // Orders comments //-------------------------------------- @@ -4077,6 +4038,12 @@ input.no-display, display: none; } + .section-config > .config { + &.collapseable { + display: none; + } + } + .accordion > dt.open, .section-config.active > .collapseable, .accordion .collapseable.open { @@ -4797,7 +4764,6 @@ input.no-display, .page-layout-admin-1column .page-columns, .catalog-product-edit, .catalog-product-new, - .sales-order-view, .catalog-category-edit { table.data { table-layout: fixed; @@ -4822,7 +4788,6 @@ input.no-display, .custom-options .data-table, .ui-dialog .data, .page-layout-admin-1column .page-columns .data, - .sales-order-view .data, .catalog-category-edit .data { word-wrap: break-word; table-layout: fixed; @@ -5074,8 +5039,6 @@ input.no-display, } } -[class*="-order-"] .admin__scope-old .order-history, -[class*="-order-"] .admin__scope-old .order-comments-history, [class*="-order-"] .admin__scope-old .order-information, [class*="-order-"] .admin__scope-old .order-billing-address, [class*="-order-"] .admin__scope-old .order-payment-method, @@ -5302,19 +5265,6 @@ input.no-display, } } -.sales-order-view { - .admin__scope-old { - .grid { - .col-name { - &:extend(.col-150-max all); - } - .col-period { - &:extend(.col-70-max all); - } - } - } -} - .sales-order-index { .admin__scope-old { .grid .col-name { @@ -5377,15 +5327,6 @@ input.no-display, } } -// Sales -> View order -[class^=' sales-order-view'] { - .admin__scope-old { - .grid .col-customer_name { - &:extend(.col-110-max all); - } - } -} - // Sales -> Return [class^=' adminhtml-rma-'] { .admin__scope-old { diff --git a/app/design/adminhtml/Magento/backend/web/css/styles.less b/app/design/adminhtml/Magento/backend/web/css/styles.less index 8b9bd439e270c0f7b8b660df3c255c3b3478f761..f4f585880c7d9d1ce9db56cf76d391b57063fb40 100644 --- a/app/design/adminhtml/Magento/backend/web/css/styles.less +++ b/app/design/adminhtml/Magento/backend/web/css/styles.less @@ -22,12 +22,11 @@ //@magento_import "source/_module.less"; // import theme styles - // // Temporary // --------------------------------------------- -// ToDo UI: Hiding menu (should be fixed in layouts) +// ToDo UI: Hiding menu (should be fixed in layouts) .attribute-popup { .page-wrapper { margin-left: 0; @@ -39,7 +38,17 @@ } } -// ToDo UI: Temporary. Should be changed +[class*='admin__'] { + + label, + + label:after, + + label:before, + &:before, + &:after { + box-sizing: border-box; + } +} + +// ToDo UI: Temporary. Should be changed @import 'source/components/_calendar-temp.less'; // diff --git a/app/design/adminhtml/Magento/backend/web/mui/styles/table.less b/app/design/adminhtml/Magento/backend/web/mui/styles/table.less index 55d1128d73b7506a05226dcfbb6c9c5c44424bbc..574b9f0754306f96ac3c0950e8ae82bd2c74a046 100644 --- a/app/design/adminhtml/Magento/backend/web/mui/styles/table.less +++ b/app/design/adminhtml/Magento/backend/web/mui/styles/table.less @@ -67,29 +67,13 @@ table { } // -// Grid table header filters and settings -//-------------------------------------- - -.grid-actions, -.pager, -.massaction, -.filter { - .input-text, - select, - .select { - margin: 0 10px 0 0; - } -} +// Table Filters +// -------------------------------------- -// -// Table Filters -//-------------------------------------- .filter { - select { - width: 99%; - } input.input-text { width: 99%; + margin-right: 0; &::-webkit-input-placeholder { color: @grid-filters-placeholder-color !important; text-transform: lowercase; diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less index d8d0b25cb90f10fa092cc096fec35d72c733fce6..486f1232621403da649c372f7f5237908cbd5e5a 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less @@ -197,9 +197,6 @@ &:first-child { padding-top: 0; } - &:last-child { - padding-bottom: 0; - } > .product { &:extend(.abs-add-clearfix all); } @@ -242,6 +239,9 @@ @_icon-font-margin: -3px 0 0 7px, @_icon-font-position: after ); + .details { + display: none; + } } } .details-qty, diff --git a/app/design/frontend/Magento/blank/composer.json b/app/design/frontend/Magento/blank/composer.json index 2a04bfacb343d811febc36cc9be67b7254e3eb41..f4cade65a82198127de39ab5b9f923dc8cb046ca 100644 --- a/app/design/frontend/Magento/blank/composer.json +++ b/app/design/frontend/Magento/blank/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-theme", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less index 3a65f3be3f3055aca8770b2ec9b94145206a63fc..365f03d8f28a56c51d26d921cb5168a0daa74983 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less @@ -205,9 +205,6 @@ &:first-child { padding-top: 0; } - &:last-child { - padding-bottom: 0; - } > .product { &:extend(.abs-add-clearfix all); } @@ -273,6 +270,9 @@ @_icon-font-position: after ); } + .details { + display: none; + } } } .details-qty, diff --git a/app/design/frontend/Magento/luma/composer.json b/app/design/frontend/Magento/luma/composer.json index 8fa8ad3aa9e7c50206b59568b7faff068e12c61b..a402aecdcb5bc449edca9a7263e1b4043526b036 100644 --- a/app/design/frontend/Magento/luma/composer.json +++ b/app/design/frontend/Magento/luma/composer.json @@ -3,12 +3,12 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/theme-frontend-blank": "0.74.0-beta6", - "magento/framework": "0.74.0-beta6", + "magento/theme-frontend-blank": "0.74.0-beta7", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-theme", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/etc/di.xml b/app/etc/di.xml index 10095a200e3bc10329a48f6a95c1fd40faa49012..7ffd8702c787b917c82fb2073953559106c98119 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -400,7 +400,7 @@ <argument name="readers" xsi:type="array"> <item name="container" xsi:type="string">Magento\Framework\View\Layout\Reader\Container</item> <item name="block" xsi:type="string">Magento\Framework\View\Layout\Reader\Block</item> - <item name="ui_component" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> + <item name="uiComponent" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> </argument> </arguments> </virtualType> @@ -416,7 +416,7 @@ <item name="block" xsi:type="string">Magento\Framework\View\Layout\Reader\Block</item> <item name="move" xsi:type="string">Magento\Framework\View\Layout\Reader\Move</item> <item name="remove" xsi:type="string">Magento\Framework\View\Layout\Reader\Remove</item> - <item name="ui_component" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> + <item name="uiComponent" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> </argument> </arguments> </virtualType> @@ -440,7 +440,7 @@ <item name="block" xsi:type="string">Magento\Framework\View\Layout\Reader\Block</item> <item name="move" xsi:type="string">Magento\Framework\View\Layout\Reader\Move</item> <item name="remove" xsi:type="string">Magento\Framework\View\Layout\Reader\Remove</item> - <item name="ui_component" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> + <item name="uiComponent" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> </argument> </arguments> </virtualType> @@ -459,7 +459,7 @@ <item name="block" xsi:type="string">Magento\Framework\View\Layout\Reader\Block</item> <item name="move" xsi:type="string">Magento\Framework\View\Layout\Reader\Move</item> <item name="remove" xsi:type="string">Magento\Framework\View\Layout\Reader\Remove</item> - <item name="ui_component" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> + <item name="uiComponent" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> </argument> </arguments> </virtualType> @@ -476,7 +476,7 @@ <item name="block" xsi:type="string">Magento\Framework\View\Layout\Reader\Block</item> <item name="move" xsi:type="string">Magento\Framework\View\Layout\Reader\Move</item> <item name="remove" xsi:type="string">Magento\Framework\View\Layout\Reader\Remove</item> - <item name="ui_component" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> + <item name="uiComponent" xsi:type="string">Magento\Framework\View\Layout\Reader\UiComponent</item> </argument> </arguments> </virtualType> @@ -501,7 +501,7 @@ <item name="body" xsi:type="object">Magento\Framework\View\Page\Config\Generator\Body</item> <item name="block" xsi:type="object">Magento\Framework\View\Layout\Generator\Block</item> <item name="container" xsi:type="object">Magento\Framework\View\Layout\Generator\Container</item> - <item name="ui_component" xsi:type="object">Magento\Framework\View\Layout\Generator\UiComponent</item> + <item name="uiComponent" xsi:type="object">Magento\Framework\View\Layout\Generator\UiComponent</item> </argument> </arguments> </type> @@ -512,7 +512,7 @@ <item name="body" xsi:type="object">Magento\Framework\View\Page\Config\Generator\Body</item> <item name="block" xsi:type="object">Magento\Framework\View\Layout\Generator\Block</item> <item name="container" xsi:type="object">Magento\Framework\View\Layout\Generator\Container</item> - <item name="ui_component" xsi:type="object">Magento\Framework\View\Layout\Generator\UiComponent</item> + <item name="uiComponent" xsi:type="object">Magento\Framework\View\Layout\Generator\UiComponent</item> </argument> </arguments> </virtualType> @@ -964,6 +964,11 @@ </argument> </arguments> </type> + <type name="Magento\Framework\Object\Copy\Config"> + <arguments> + <argument name="dataStorage" xsi:type="object">Magento\Framework\Object\Copy\Config\Data\Proxy</argument> + </arguments> + </type> <type name="Magento\Framework\Object\Copy\Config\Reader"> <arguments> <argument name="fileName" xsi:type="string">fieldset.xml</argument> @@ -1101,4 +1106,9 @@ </argument> </arguments> </type> + <type name="Magento\Framework\Url\Decoder"> + <arguments> + <argument name="urlBuilder" xsi:type="object">Magento\Framework\UrlInterface\Proxy</argument> + </arguments> + </type> </config> diff --git a/app/i18n/magento/de_de/composer.json b/app/i18n/magento/de_de/composer.json index 3348716f124bbb1283aca8365bee6dc1653f53b6..d1331eacdfd3c24651ca62a9c24998294c5fef7f 100644 --- a/app/i18n/magento/de_de/composer.json +++ b/app/i18n/magento/de_de/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-de_de", "description": "German (Germany) language", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/en_us/composer.json b/app/i18n/magento/en_us/composer.json index 54427d660fa30d9bae85106145c1486e6e04189d..7ba926a7e7f131d32dcc6970e6a8e5354f1b9de0 100644 --- a/app/i18n/magento/en_us/composer.json +++ b/app/i18n/magento/en_us/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-en_us", "description": "English (United States) language", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/es_es/composer.json b/app/i18n/magento/es_es/composer.json index de93f29f35665cc28056a6bd9d273ac9a85cf89c..7499abd7c6c5e1e7f99c0aafa4db0235b5313dd5 100644 --- a/app/i18n/magento/es_es/composer.json +++ b/app/i18n/magento/es_es/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-es_es", "description": "Spanish (Spain) language", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/fr_fr/composer.json b/app/i18n/magento/fr_fr/composer.json index 57c2be2ed896269ff4140ad4c4970cb450ba2b67..17a7589ee6a23fde6f076caba6a050244d4be4d3 100644 --- a/app/i18n/magento/fr_fr/composer.json +++ b/app/i18n/magento/fr_fr/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-fr_fr", "description": "French (France) language", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/nl_nl/composer.json b/app/i18n/magento/nl_nl/composer.json index 12c4f56f07432845832714823d15a4f34d8e4b10..38bd3b93c1f0670ba4cc1bcddfd8411834492f4a 100644 --- a/app/i18n/magento/nl_nl/composer.json +++ b/app/i18n/magento/nl_nl/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-nl_nl", "description": "Dutch (Netherlands) language", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/pt_br/composer.json b/app/i18n/magento/pt_br/composer.json index cc1a364b3dde8fba1615b23368ee82f4041da639..240415c9b81456f5a57fdb00cafcabcb1a312639 100644 --- a/app/i18n/magento/pt_br/composer.json +++ b/app/i18n/magento/pt_br/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-pt_br", "description": "Portuguese (Brazil) language", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/zh_cn/composer.json b/app/i18n/magento/zh_cn/composer.json index 1088c0e650ce72ad7a50a07957c4571f156913f2..28227ddf118f2d71115548176e258f08116a2f0c 100644 --- a/app/i18n/magento/zh_cn/composer.json +++ b/app/i18n/magento/zh_cn/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-zh_cn", "description": "Chinese (China) language", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta6", + "magento/framework": "0.74.0-beta7", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/composer.json b/composer.json index e99f901fde5affb0c5023710e7e9d788421aa9d0..4424cb729baf30a8a1b65ed83e644d65296a9e96 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "magento/magento2ce", "description": "Magento 2 (Community Edition)", "type": "project", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/composer.lock b/composer.lock index a4498fe8e6dc972a67cd464639b3f4a7619783fd..1458a41878a67fefec425b795aad2b31fbfde8ab 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "ff2c069b557199903bafc88e8abe0cea", + "hash": "eb32c28075b2f343240b21d18a62385e", "packages": [ { "name": "composer/composer", diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/data_object.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/service_data_attributes.xml similarity index 69% rename from dev/tests/api-functional/_files/Magento/TestModule1/etc/data_object.xml rename to dev/tests/api-functional/_files/Magento/TestModule1/etc/service_data_attributes.xml index de2236e2195f380aedd5614447065bc9e480f7aa..fa96514a063b6112004e7a6073a2cc131a87f44c 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule1/etc/data_object.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/service_data_attributes.xml @@ -5,13 +5,13 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\TestModule1\Service\V1\Entity\Item"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\TestModule1\Service\V1\Entity\Item"> <attribute code="custom_attribute_data_object" type="Magento\TestModuleMSC\Model\Data\CustomAttributeDataObject" /> <attribute code="custom_attribute_string" type="string" /> - </custom_attributes> - <custom_attributes for="Magento\TestModuleMSC\Model\Data\CustomAttributeDataObject"> + </extension_attributes> + <extension_attributes for="Magento\TestModuleMSC\Model\Data\CustomAttributeDataObject"> <attribute code="custom_attribute_nested" type="Magento\TestModuleMSC\Model\Data\CustomAttributeNestedDataObject" /> <attribute code="custom_attribute_int" type="int" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/data_object.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/service_data_attributes.xml similarity index 69% rename from dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/data_object.xml rename to dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/service_data_attributes.xml index ece2b1f581775daa25e1acec4f4fc120a876c431..f11e639ccd2753296d65071cf32f3e5fb47e0e7d 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/data_object.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/service_data_attributes.xml @@ -5,13 +5,13 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\TestModuleMSC\Api\Data\ItemInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\TestModuleMSC\Api\Data\ItemInterface"> <attribute code="custom_attribute_data_object" type="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface" /> <attribute code="custom_attribute_string" type="string" /> - </custom_attributes> - <custom_attributes for="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface"> + </extension_attributes> + <extension_attributes for="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface"> <attribute code="custom_attribute_nested" type="Magento\TestModuleMSC\Api\Data\CustomAttributeNestedDataObjectInterface" /> <attribute code="custom_attribute_int" type="int" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/dev/tests/api-functional/config/install-config-mysql.php.dist b/dev/tests/api-functional/config/install-config-mysql.php.dist index 535cfb7232e8f1ef2a58a98916fe49b98bea5d6a..2f19ce10e80503908aadeea6ddaca761808bb4f3 100644 --- a/dev/tests/api-functional/config/install-config-mysql.php.dist +++ b/dev/tests/api-functional/config/install-config-mysql.php.dist @@ -9,22 +9,22 @@ return [ 'language' => 'en_US', 'timezone' => 'America/Los_Angeles', 'currency' => 'USD', - 'db_host' => 'localhost', - 'db_name' => 'magento_functional_tests', - 'db_user' => 'root', - 'db_password' => '', - 'backend_frontname' => 'backend', - 'base_url' => 'http://localhost/', - 'use_secure' => '0', - 'use_rewrites' => '0', - 'admin_lastname' => 'Admin', - 'admin_firstname' => 'Admin', - 'admin_email' => 'admin@example.com', - 'admin_user' => 'admin', - 'admin_password' => '123123q', - 'admin_use_security_key' => '0', + 'db-host' => 'localhost', + 'db-name' => 'magento_functional_tests', + 'db-user' => 'root', + 'db-password' => '', + 'backend-frontname' => 'backend', + 'base-url' => 'http://localhost/', + 'use-secure' => '0', + 'use-rewrites' => '0', + 'admin-lastname' => 'Admin', + 'admin-firstname' => 'Admin', + 'admin-email' => 'admin@example.com', + 'admin-user' => 'admin', + 'admin-password' => '123123q', + 'admin-use-security-key' => '0', /* PayPal has limitation for order number - 20 characters. 10 digits prefix + 8 digits number is good enough */ - 'sales_order_increment_prefix' => time(), - 'session_save' => 'db', - 'cleanup_database' => true, + 'sales-order-increment-prefix' => time(), + 'session-save' => 'db', + 'cleanup-database' => true, ]; diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index fb6588a7f4107cf2ff07095ff3820e442ee10a87..a0f06e0ce7aac3fa6752c18a2adb47af1ba2e544 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -126,7 +126,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract public function testProductLinks() { - $this->markTestSkipped('Skipped until MAGETWO-35458 is ready'); // Create simple product $productData = [ ProductInterface::SKU => "product_simple_500", @@ -140,9 +139,10 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract ]; $this->saveProduct($productData); + $productLinkData = ["product_sku" => "product_simple_with_related_500", "link_type" => "related", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", - "position" => 0]; + "position" => 0, "extension_attributes" => []]; $productWithRelatedData = [ ProductInterface::SKU => "product_simple_with_related_500", ProductInterface::NAME => "Product Simple with Related 500", @@ -166,7 +166,7 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract // update link information $productLinkData = ["product_sku" => "product_simple_with_related_500", "link_type" => "upsell", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", - "position" => 0]; + "position" => 0, "extension_attributes" => []]; $productWithUpsellData = [ ProductInterface::SKU => "product_simple_with_related_500", ProductInterface::NAME => "Product Simple with Related 500", @@ -174,7 +174,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract ProductInterface::TYPE_ID => 'simple', ProductInterface::PRICE => 100, ProductInterface::STATUS => 1, - ProductInterface::TYPE_ID => 'simple', ProductInterface::ATTRIBUTE_SET_ID => 4, "product_links" => [$productLinkData] ]; @@ -195,18 +194,15 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract ProductInterface::TYPE_ID => 'simple', ProductInterface::PRICE => 100, ProductInterface::STATUS => 1, - ProductInterface::TYPE_ID => 'simple', ProductInterface::ATTRIBUTE_SET_ID => 4, "product_links" => [] ]; $this->saveProduct($productWithNoLinkData); $response = $this->getProduct("product_simple_with_related_500"); - $this->assertArrayHasKey('product_links', $response); $links = $response['product_links']; - $this->assertEquals(1, count($links)); - $this->assertEquals([], $links[0]); + $this->assertEquals([], $links); $this->deleteProduct("product_simple_500"); $this->deleteProduct("product_simple_with_related_500"); diff --git a/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/ProductRepositoryInterfaceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0a5a6a9faa72c64b8ceb5dcce87fd81f55ec92f3 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/ProductRepositoryInterfaceTest.php @@ -0,0 +1,398 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogInventory\Api; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\CatalogInventory\Api\Data\StockStatusInterface; +use Magento\Framework\Api\ExtensibleDataInterface; +use Magento\TestFramework\TestCase\WebapiAbstract; + +class ProductRepositoryInterfaceTest extends WebapiAbstract +{ + const SERVICE_NAME = 'catalogProductRepositoryV1'; + const SERVICE_VERSION = 'V1'; + const RESOURCE_PATH = '/V1/products'; + + const KEY_EXTENSION_ATTRIBUTES = ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY; + const KEY_STOCK_ITEM = StockStatusInterface::STOCK_ITEM; + const KEY_QTY = StockStatusInterface::QTY; + const KEY_ITEM_ID = 'item_id'; + const KEY_PRODUCT_ID = StockStatusInterface::PRODUCT_ID; + const KEY_WEBSITE_ID = StockStatusInterface::WEBSITE_ID; + const KEY_CUSTOM_ATTRIBUTES = 'custom_attributes'; + const KEY_ATTRIBUTE_CODE = \Magento\Eav\Api\Data\AttributeInterface::ATTRIBUTE_CODE; + const CODE_QUANTITY_AND_STOCK_STATUS = 'quantity_and_stock_status'; + + const PRODUCT_SKU = 'sku-test-catalog-inventory'; + + /** + * Tests the 'happy path' + */ + public function testCatalogInventory() + { + // create a simple product with catalog inventory + $qty = 1234; + $productData = $this->getSimpleProductData($qty); + $stockItemData = $this->getStockItemData($qty); + $this->assertArrayNotHasKey(self::KEY_ITEM_ID, $stockItemData); + $this->assertArrayNotHasKey(self::KEY_WEBSITE_ID, $stockItemData); + $this->assertArrayNotHasKey(self::KEY_PRODUCT_ID, $stockItemData); + $productData[self::KEY_EXTENSION_ATTRIBUTES] = $stockItemData; + + $response = $this->saveProduct($productData); + + $this->assertArrayHasKey(self::KEY_EXTENSION_ATTRIBUTES, $response); + $this->assertTrue(isset($response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM])); + $stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]; + $returnedQty = $stockItemData[self::KEY_QTY]; + $this->assertEquals($qty, $returnedQty, 'CREATE: Expected qty to be same: ' . $qty .', '. $returnedQty); + $this->assertArrayHasKey(self::KEY_ITEM_ID, $stockItemData); + $this->assertArrayHasKey(self::KEY_PRODUCT_ID, $stockItemData); + $this->assertArrayHasKey(self::KEY_WEBSITE_ID, $stockItemData); + + // officially get the product + $response = $this->getProduct($productData[ProductInterface::SKU]); + + $stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]; + $returnedQty = $stockItemData[self::KEY_QTY]; + $this->assertEquals($qty, $returnedQty, 'GET: Expected qty to be same: ' . $qty .', '. $returnedQty); + + // update the catalog inventory + $qty = $this->getDifferent($qty); // update the quantity + $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM][self::KEY_QTY] = $qty; + + $response = $this->updateProduct($response); + + $stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]; + $returnedQty = $stockItemData[self::KEY_QTY]; + $this->assertEquals($qty, $returnedQty, 'UPDATE 1: Expected qty to be same: ' . $qty .', '. $returnedQty); + + $customAttributeQty = $this->findCustomAttributeQty($response[self::KEY_CUSTOM_ATTRIBUTES]); + $this->assertTrue(!is_bool($customAttributeQty), 'Expected to find a quantity in the custom attributes'); + $this->assertEquals( + $qty, + $customAttributeQty, + 'UPDATE 1: Expected custom attribute qty to be updated: ' . $qty .', '. $customAttributeQty + ); + + // update the product without any mention of catalog inventory; no change expected for catalog inventory + // note: $qty expected to be the same as previously set, above + $newPrice = $this->getDifferent($response[ProductInterface::PRICE]); + $response[ProductInterface::PRICE] = $newPrice; + unset($response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]); + + $response = $this->updateProduct($response); + + $this->assertArrayHasKey(self::KEY_EXTENSION_ATTRIBUTES, $response); + $this->assertTrue(isset($response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM])); + $stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]; + $returnedQty = $stockItemData[self::KEY_QTY]; + $this->assertEquals($qty, $returnedQty, 'UPDATE 2: Expected qty to be same: ' . $qty .', '. $returnedQty); + $this->assertEquals($newPrice, $response[ProductInterface::PRICE]); + + // delete the product; expect that all goes well + $response = $this->deleteProduct($productData[ProductInterface::SKU]); + $this->assertTrue($response); + } + + /** + * Tests conditions that stray from the 'happy path' + */ + public function testCatalogInventoryWithBogusData() + { + // create a simple product with catalog inventory + $qty = 666; + $productData = $this->getSimpleProductData($qty); + $stockItemData = $this->getStockItemData($qty); + $this->assertArrayNotHasKey(self::KEY_ITEM_ID, $stockItemData); + $this->assertArrayNotHasKey(self::KEY_WEBSITE_ID, $stockItemData); + $this->assertArrayNotHasKey(self::KEY_PRODUCT_ID, $stockItemData); + $productData[self::KEY_EXTENSION_ATTRIBUTES] = $stockItemData; + + $response = $this->saveProduct($productData); + + $this->assertArrayHasKey(self::KEY_EXTENSION_ATTRIBUTES, $response); + $this->assertTrue(isset($response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM])); + $stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]; + $returnedQty = $stockItemData[self::KEY_QTY]; + $this->assertEquals($qty, $returnedQty, 'POST 1: Expected qty to be same: ' . $qty .', '. $returnedQty); + $this->assertArrayHasKey(self::KEY_ITEM_ID, $stockItemData); + $this->assertArrayHasKey(self::KEY_PRODUCT_ID, $stockItemData); + $this->assertArrayHasKey(self::KEY_WEBSITE_ID, $stockItemData); + + // re-save the catalog inventory: + // -- update quantity (which should be honored) + // -- supply an incorrect product id (which should be ignored, and be replaced with the actual one) + // -- supply an incorrect website id (which should be ignored, and be replaced with the actual one) + $qty = 777; // update the quantity + $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM][self::KEY_QTY] = $qty; + + $originalProductId = $stockItemData[self::KEY_PRODUCT_ID]; + $bogusProductId = $this->getDifferent($originalProductId); + $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM][self::KEY_PRODUCT_ID] = $bogusProductId; + + $originalWebsiteId = $stockItemData[self::KEY_WEBSITE_ID]; + $bogusWebsiteId = $this->getDifferent($originalWebsiteId); + $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM][self::KEY_WEBSITE_ID] = $bogusWebsiteId; + + $response = $this->saveProduct($response); + + $stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]; + $returnedQty = $stockItemData[self::KEY_QTY]; + $this->assertEquals($qty, $returnedQty, 'POST 2: Expected qty to be same: ' . $qty .', '. $returnedQty); + + $returnedProductId = $stockItemData[self::KEY_PRODUCT_ID]; + $this->assertEquals($originalProductId, $returnedProductId); + + $returnedWebsiteId = $stockItemData[self::KEY_WEBSITE_ID]; + $this->assertEquals($originalWebsiteId, $returnedWebsiteId); + + // delete the product; expect that all goes well + $response = $this->deleteProduct($productData[ProductInterface::SKU]); + $this->assertTrue($response); + } + + /** + * Tests that creating a simple product has a side-effect of creating catalog inventory + */ + public function testSimpleProductCreationWithoutSpecifyingCatalogInventory() + { + // create a simple product with catalog inventory + $qty = null; + $productData = $this->getSimpleProductData($qty); + $this->assertArrayNotHasKey(self::KEY_CUSTOM_ATTRIBUTES, $productData); + $this->assertArrayNotHasKey(self::KEY_EXTENSION_ATTRIBUTES, $productData); + + $response = $this->saveProduct($productData); + + $this->assertArrayHasKey(self::KEY_EXTENSION_ATTRIBUTES, $response); + $this->assertTrue(isset($response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM])); + $stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]; + $this->assertArrayHasKey(self::KEY_ITEM_ID, $stockItemData); + $this->assertArrayHasKey(self::KEY_PRODUCT_ID, $stockItemData); + $this->assertArrayHasKey(self::KEY_WEBSITE_ID, $stockItemData); + + // delete the product; expect that all goes well + $response = $this->deleteProduct($productData[ProductInterface::SKU]); + $this->assertTrue($response); + } + + // --- my helpers ----------------------------------------------------------------------------- + + /** + * Return a value that is different than the original one + * + * @param int $original + * @return int + */ + protected function getDifferent($original) + { + return 1 + $original * $original; + } + + /** + * Returns the product's quantity from the array of custom attributes. + * If no quantity can be found, will return false. + * + * @param array $customAttributes + * @return int|bool + */ + protected function findCustomAttributeQty($customAttributes) + { + $qty = false; + $qtyAndStockStatus = []; + foreach ($customAttributes as $customAttribute) { + if ($customAttribute[self::KEY_ATTRIBUTE_CODE] == self::CODE_QUANTITY_AND_STOCK_STATUS) { + $qtyAndStockStatus = $customAttribute['value']; + break; + } + } + if (!empty($qtyAndStockStatus) && is_array($qtyAndStockStatus)) { + + if (array_key_exists('any_type', $qtyAndStockStatus)) { + // for SOAP, need to use the inner array + $qtyAndStockStatus = $qtyAndStockStatus['any_type']; + } + + // ex: [true, 1234] + if (is_bool($qtyAndStockStatus[0]) || is_string($qtyAndStockStatus[0])) { + $qty = $qtyAndStockStatus[1]; + } else { + $qty = $qtyAndStockStatus[0]; + } + } + return $qty; + } + + /** + * Get Simple Product Data + * + * @param int $qty + * @return array + */ + protected function getSimpleProductData($qty = 1000) + { + $productData = [ + ProductInterface::SKU => self::PRODUCT_SKU, + ProductInterface::NAME => self::PRODUCT_SKU, + ProductInterface::VISIBILITY => 4, + ProductInterface::TYPE_ID => 'simple', + ProductInterface::PRICE => 10, + ProductInterface::STATUS => 1, + ProductInterface::ATTRIBUTE_SET_ID => 4, + ]; + + if ($qty != null) { + $productData[self::KEY_CUSTOM_ATTRIBUTES] = [ + [self::KEY_ATTRIBUTE_CODE => 'description', 'value' => 'My Product Description'], + [self::KEY_ATTRIBUTE_CODE => self::CODE_QUANTITY_AND_STOCK_STATUS, 'value' => [true, $qty]], + ]; + } + + return $productData; + } + + /** + * Get sample Stock Item data + * + * @param int $qty + * @return array + */ + protected function getStockItemData($qty = 1000) + { + return [ + self::KEY_STOCK_ITEM => [ + self::KEY_QTY => $qty, + 'is_in_stock' => true, + 'is_qty_decimal' => false, + 'show_default_notification_message' => false, + 'use_config_min_qty' => true, + 'min_qty' => 0, + 'use_config_min_sale_qty' => 1, + 'min_sale_qty' => 1, + 'use_config_max_sale_qty' => true, + 'max_sale_qty' => 10000, + 'use_config_backorders' => true, + 'backorders' => 0, + 'use_config_notify_stock_qty' => true, + 'notify_stock_qty' => 1, + 'use_config_qty_increments' => true, + 'qty_increments' => 0, + 'use_config_enable_qty_inc' => false, + 'enable_qty_increments' => false, + 'use_config_manage_stock' => false, + 'manage_stock' => true, + 'low_stock_date' => "0", + 'is_decimal_divided' => false, + 'stock_status_changed_auto' => 0, + ] + ]; + } + + // --- common REST helpers -------------------------------------------------------------------- + + /** + * Get a product via its sku + * + * @param string $sku + * @return array the product data + */ + protected function getProduct($sku) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Get', + ], + ]; + + $response = $this->_webApiCall($serviceInfo, ['sku' => $sku]); + return $response; + } + + /** + * Save a product + * + * @param array $product + * @return array the created product data + */ + protected function saveProduct($product) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } + + /** + * Update an existing product via its sku + * + * @param array $product + * @return array the product data, including any updates + */ + protected function updateProduct($product) + { + $sku = $product[ProductInterface::SKU]; + if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) { + $product[ProductInterface::SKU] = null; + } + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } + + /** + * Delete a product via its sku + * + * @param string $sku + * @return bool + */ + protected function deleteProduct($sku) + { + $resourcePath = self::RESOURCE_PATH . '/' . $sku; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $resourcePath, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'deleteById', + ], + ]; + $requestData = ['sku' => $sku]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockItemTest.php b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockItemTest.php index 0513f5e68abfdbe603bb5972604abb8d21453165..f8ef77f8e297b3bdf6a41c501c70adb40d31db99 100644 --- a/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockItemTest.php +++ b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockItemTest.php @@ -223,7 +223,7 @@ class StockItemTest extends WebapiAbstract 'enable_qty_increments' => '', 'use_config_manage_stock' => 1, 'manage_stock' => 1, - 'low_stock_date' => 0, + 'low_stock_date' => '', 'is_decimal_divided' => '', 'stock_status_changed_auto' => 0 ], diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php index 4551eaa3e45e2d713487938cf485344c5ff10b5c..bf9607d24969cae9ad70a61e46973c1ce2d95fb3 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php @@ -166,7 +166,6 @@ class OptionRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstrac ]; $option = [ 'attribute_id' => 'test_configurable', - 'type' => 'select', 'label' => 'Test', 'values' => [ [ diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionTypesListTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionTypesListTest.php deleted file mode 100644 index a96d5ca79a5cb22ccf148210a39a37f0b545ba81..0000000000000000000000000000000000000000 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionTypesListTest.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\ConfigurableProduct\Api; - -class OptionTypesListTest extends \Magento\TestFramework\TestCase\WebapiAbstract -{ - const SERVICE_READ_NAME = 'configurableProductOptionTypesListV1'; - const SERVICE_VERSION = 'V1'; - const RESOURCE_PATH = '/V1/configurable-products/:sku/options/'; - - public function testGetTypes() - { - $expectedTypes = ['multiselect', 'select']; - $result = $this->getTypes(); - $this->assertEquals($expectedTypes, $result); - } - - /** - * @return array - */ - protected function getTypes() - { - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => str_replace(':sku/', '', self::RESOURCE_PATH) . 'types', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET - ], - 'soap' => [ - 'service' => self::SERVICE_READ_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_READ_NAME . 'GetItems' - ] - ]; - return $this->_webApiCall($serviceInfo); - } -} diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b9a2c658dfa3bd771656523fa6a3669ec2eaf411 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php @@ -0,0 +1,486 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Api; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\Api\ExtensibleDataInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; + +/** + * Class ProductRepositoryTest for testing ConfigurableProduct integration + */ +class ProductRepositoryTest extends WebapiAbstract +{ + const SERVICE_NAME = 'catalogProductRepositoryV1'; + const SERVICE_VERSION = 'V1'; + const RESOURCE_PATH = '/V1/products'; + const CONFIGURABLE_PRODUCT_SKU = 'configurable-product-sku'; + + /** + * @var \Magento\Eav\Model\Config + */ + protected $eavConfig; + + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $objectManager; + + /** + * @var \Magento\Catalog\Model\Entity\Attribute + */ + protected $configurableAttribute; + + /** + * Execute per test initialization + */ + public function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->eavConfig = $this->objectManager->get('Magento\Eav\Model\Config'); + } + + /** + * Execute per test cleanup + */ + public function tearDown() + { + $this->deleteProductBySku(self::CONFIGURABLE_PRODUCT_SKU); + parent::tearDown(); + } + + protected function getConfigurableAttributeOptions() + { + /** @var \Magento\Eav\Model\Resource\Entity\Attribute\Option\Collection $optionCollection */ + $optionCollection = $this->objectManager->create( + 'Magento\Eav\Model\Resource\Entity\Attribute\Option\Collection' + ); + $options = $optionCollection->setAttributeFilter($this->configurableAttribute->getId())->getData(); + return $options; + } + + protected function createConfigurableProduct() + { + $productId1 = 10; + $productId2 = 20; + + $label = "color"; + + $this->configurableAttribute = $this->eavConfig->getAttribute('catalog_product', 'test_configurable'); + $this->assertNotNull($this->configurableAttribute); + + $options = $this->getConfigurableAttributeOptions(); + $this->assertEquals(2, count($options)); + + $configurableProductOptions = [ + [ + "attribute_id" => $this->configurableAttribute->getId(), + "label" => $label, + "position" => 0, + "values" => [ + [ + "pricing_value" => 10, + "is_percent" => 0, + "value_index" => $options[0]['option_id'], + ], + [ + "pricing_value" => 5, + "is_percent" => 1, + "value_index" => $options[1]['option_id'], + ] + ], + ] + ]; + + $product = [ + "sku" => self::CONFIGURABLE_PRODUCT_SKU, + "name" => self::CONFIGURABLE_PRODUCT_SKU, + "type_id" => "configurable", + "price" => 50, + 'attribute_set_id' => 4, + "custom_attributes" => [ + [ + "attribute_code" => $this->configurableAttribute->getAttributeCode(), + "value" => $options[0]['option_id'], + ], + ], + "extension_attributes" => [ + "configurable_product_options" => $configurableProductOptions, + "configurable_product_links" => [$productId1, $productId2], + ], + ]; + + $response = $this->createProduct($product); + return $response; + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testCreateConfigurableProduct() + { + $productId1 = 10; + $productId2 = 20; + $label = "color"; + + $response = $this->createConfigurableProduct(); + $this->assertEquals(self::CONFIGURABLE_PRODUCT_SKU, $response[ProductInterface::SKU]); + $this->assertEquals(50, $response['price']); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]) + ); + $resultConfigurableProductOptions + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]; + $this->assertEquals(1, count($resultConfigurableProductOptions)); + $this->assertTrue(isset($resultConfigurableProductOptions[0]['label'])); + $this->assertTrue(isset($resultConfigurableProductOptions[0]['id'])); + $this->assertEquals($label, $resultConfigurableProductOptions[0]['label']); + $this->assertTrue( + isset($resultConfigurableProductOptions[0]['values']) + ); + $this->assertEquals(2, count($resultConfigurableProductOptions[0]['values'])); + + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_links"]) + ); + $resultConfigurableProductLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_links"]; + $this->assertEquals(2, count($resultConfigurableProductLinks)); + + $this->assertEquals([$productId1, $productId2], $resultConfigurableProductLinks); + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testDeleteConfigurableProductOption() + { + $productId1 = 10; + $productId2 = 20; + + $response = $this->createConfigurableProduct(); + //delete existing option + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options'] = []; + //leave the product links unchanged + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_links']); + $response = $this->saveProduct($response); + + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]) + ); + $resultConfigurableProductOptions + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]; + $this->assertEquals(0, count($resultConfigurableProductOptions)); + + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_links"]) + ); + $resultConfigurableProductLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_links"]; + $this->assertEquals(2, count($resultConfigurableProductLinks)); + + $this->assertEquals([$productId1, $productId2], $resultConfigurableProductLinks); + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testUpdateConfigurableProductOption() + { + $productId1 = 10; + $newLabel = 'size'; + + $response = $this->createConfigurableProduct(); + $option = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"][0]; + + $optionId = $option['id']; + $updatedOption = [ + 'id' => $optionId, + 'attribute_id' => $option['attribute_id'], + 'label' => $newLabel, + 'position' => 1, + 'values' => [ + [ + 'pricing_value' => 15, + 'is_percent' => 1, + 'value_index' => $option['values'][0]['value_index'], + ], + ], + ]; + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options'][0] = + $updatedOption; + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_links'] = [$productId1]; + $response = $this->saveProduct($response); + + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]) + ); + $resultConfigurableProductOptions + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]; + $this->assertEquals(1, count($resultConfigurableProductOptions)); + + $this->assertEquals($updatedOption, $resultConfigurableProductOptions[0]); + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testUpdateConfigurableProductLinks() + { + $productId1 = 10; + $productId2 = 20; + + $response = $this->createConfigurableProduct(); + $options = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options']; + //leave existing option untouched + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options']); + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_links'] = [$productId1]; + $response = $this->saveProduct($response); + + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]) + ); + $resultConfigurableProductOptions + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_options"]; + $this->assertEquals(1, count($resultConfigurableProductOptions)); + //Since one product is removed, the available values for the option is reduced + $this->assertEquals(1, count($resultConfigurableProductOptions[0]['values'])); + + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_links"]) + ); + $resultConfigurableProductLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_links"]; + $this->assertEquals(1, count($resultConfigurableProductLinks)); + $this->assertEquals([$productId1], $resultConfigurableProductLinks); + + //adding back the product links, the option value should be restored + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options']); + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_links'] + = [$productId1, $productId2]; + //set the value for required attribute + $response["custom_attributes"][] = + [ + "attribute_code" => $this->configurableAttribute->getAttributeCode(), + "value" => $resultConfigurableProductOptions[0]['values'][0]['value_index'], + ]; + + $response = $this->saveProduct($response); + $currentOptions = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options']; + + $this->assertEquals($options, $currentOptions); + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testUpdateConfigurableProductLinksWithNonExistingProduct() + { + $productId1 = 10; + $nonExistingId = 999; + + $response = $this->createConfigurableProduct(); + //leave existing option untouched + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options']); + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_links'] = [ + $productId1, $nonExistingId + ]; + + $expectedMessage = 'Product with id "%1" does not exist.'; + try { + $this->saveProduct($response); + $this->fail("Expected exception"); + } catch (\SoapFault $e) { + $this->assertContains( + $expectedMessage, + $e->getMessage(), + "SoapFault does not contain expected message." + ); + } catch (\Exception $e) { + $errorObj = $this->processRestExceptionResult($e); + $this->assertEquals($expectedMessage, $errorObj['message']); + $this->assertEquals(['0' => '999'], $errorObj['parameters']); + } + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testUpdateConfigurableProductLinksWithDuplicateAttributes() + { + $productId1 = 10; + $productId2 = 20; + + $response = $this->createConfigurableProduct(); + $options = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options']; + //make product2 and product1 have the same value for the configurable attribute + $optionValue1 = $options[0]['values'][0]['value_index']; + $product2 = $this->getProduct('simple_' . $productId2); + $product2['custom_attributes'] = [ + [ + 'attribute_code' => 'test_configurable', + 'value' => $optionValue1, + ] + ]; + $this->saveProduct($product2); + + //leave existing option untouched + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options']); + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_links'] = [ + $productId1, $productId2 + ]; + + $expectedMessage = 'Products "%1" and %2 have the same set of attribute values.'; + try { + $this->saveProduct($response); + $this->fail("Expected exception"); + } catch (\SoapFault $e) { + $this->assertContains( + $expectedMessage, + $e->getMessage(), + "SoapFault does not contain expected message." + ); + } catch (\Exception $e) { + $errorObj = $this->processRestExceptionResult($e); + $this->assertEquals($expectedMessage, $errorObj['message']); + $this->assertEquals(['0' => 20, '1' => 10], $errorObj['parameters']); + } + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testUpdateConfigurableProductLinksWithWithoutVariationAttributes() + { + $productId1 = 10; + $productId2 = 20; + + $response = $this->createConfigurableProduct(); + + /** delete all variation attribute */ + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options'] = []; + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_links'] = [ + $productId1, $productId2 + ]; + + $expectedMessage = 'The configurable product does not have any variation attribute.'; + try { + $this->saveProduct($response); + $this->fail("Expected exception"); + } catch (\SoapFault $e) { + $this->assertContains( + $expectedMessage, + $e->getMessage(), + "SoapFault does not contain expected message." + ); + } catch (\Exception $e) { + $errorObj = $this->processRestExceptionResult($e); + $this->assertEquals($expectedMessage, $errorObj['message']); + } + } + + /** + * Get product + * + * @param string $productSku + * @return array the product data + */ + protected function getProduct($productSku) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $productSku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Get', + ], + ]; + + $response = (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ? + $this->_webApiCall($serviceInfo, ['sku' => $productSku]) : $this->_webApiCall($serviceInfo); + + return $response; + } + + /** + * Create product + * + * @param array $product + * @return array the created product data + */ + protected function createProduct($product) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } + + /** + * Delete a product by sku + * + * @param $productSku + * @return bool + */ + protected function deleteProductBySku($productSku) + { + $resourcePath = self::RESOURCE_PATH . '/' . $productSku; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $resourcePath, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'deleteById', + ], + ]; + $requestData = ["sku" => $productSku]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } + + /** + * Save product + * + * @param array $product + * @return array the created product data + */ + protected function saveProduct($product) + { + $resourcePath = self::RESOURCE_PATH . '/' . $product['sku']; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $resourcePath, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php index 4234afc66f27883af89395192189e18bf3c154e0..656da53f38e842a1f3122b6fd35fbd87cdb24c05 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php @@ -80,9 +80,10 @@ class LinkRepositoryTest extends WebapiAbstract protected function getTargetProduct($isScopeGlobal = false) { $objectManager = Bootstrap::getObjectManager(); - $product = $objectManager->get('Magento\Catalog\Model\ProductFactory')->create()->load(1); if ($isScopeGlobal) { - $product->setStoreId(0); + $product = $objectManager->get('Magento\Catalog\Model\ProductFactory')->create()->setStoreId(0)->load(1); + } else { + $product = $objectManager->get('Magento\Catalog\Model\ProductFactory')->create()->load(1); } return $product; @@ -114,18 +115,18 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => true, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Title', 'sort_order' => 1, 'price' => 10.1, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_type' => 'file', - 'link_file' => [ + 'link_file_content' => [ 'file_data' => base64_encode(file_get_contents($this->testImagePath)), 'name' => 'image.jpg', ], - 'sample_file' => [ + 'sample_file_content' => [ 'file_data' => base64_encode(file_get_contents($this->testImagePath)), 'name' => 'image.jpg', ], @@ -137,15 +138,15 @@ class LinkRepositoryTest extends WebapiAbstract $globalScopeLink = $this->getTargetLink($this->getTargetProduct(true), $newLinkId); $link = $this->getTargetLink($this->getTargetProduct(), $newLinkId); $this->assertNotNull($link); - $this->assertEquals($requestData['linkContent']['title'], $link->getTitle()); - $this->assertEquals($requestData['linkContent']['title'], $globalScopeLink->getTitle()); - $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder()); - $this->assertEquals($requestData['linkContent']['price'], $link->getPrice()); - $this->assertEquals($requestData['linkContent']['price'], $globalScopeLink->getPrice()); - $this->assertEquals($requestData['linkContent']['shareable'], $link->getIsShareable()); - $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads()); - $this->assertEquals($requestData['linkContent']['link_type'], $link->getLinkType()); - $this->assertEquals($requestData['linkContent']['sample_type'], $link->getSampleType()); + $this->assertEquals($requestData['link']['title'], $link->getTitle()); + $this->assertEquals($requestData['link']['title'], $globalScopeLink->getTitle()); + $this->assertEquals($requestData['link']['sort_order'], $link->getSortOrder()); + $this->assertEquals($requestData['link']['price'], $link->getPrice()); + $this->assertEquals($requestData['link']['price'], $globalScopeLink->getPrice()); + $this->assertEquals($requestData['link']['is_shareable'], $link->getIsShareable()); + $this->assertEquals($requestData['link']['number_of_downloads'], $link->getNumberOfDownloads()); + $this->assertEquals($requestData['link']['link_type'], $link->getLinkType()); + $this->assertEquals($requestData['link']['sample_type'], $link->getSampleType()); $this->assertStringEndsWith('.jpg', $link->getSampleFile()); $this->assertStringEndsWith('.jpg', $link->getLinkFile()); $this->assertNull($link->getLinkUrl()); @@ -160,11 +161,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Store View Title', 'sort_order' => 1, 'price' => 150, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_url' => 'http://www.example.com/', 'link_type' => 'url', @@ -177,15 +178,15 @@ class LinkRepositoryTest extends WebapiAbstract $link = $this->getTargetLink($this->getTargetProduct(), $newLinkId); $globalScopeLink = $this->getTargetLink($this->getTargetProduct(true), $newLinkId); $this->assertNotNull($link); - $this->assertEquals($requestData['linkContent']['title'], $link->getTitle()); - $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder()); - $this->assertEquals($requestData['linkContent']['price'], $link->getPrice()); - $this->assertEquals($requestData['linkContent']['shareable'], $link->getIsShareable()); - $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads()); - $this->assertEquals($requestData['linkContent']['link_url'], $link->getLinkUrl()); - $this->assertEquals($requestData['linkContent']['link_type'], $link->getLinkType()); - $this->assertEquals($requestData['linkContent']['sample_url'], $link->getSampleUrl()); - $this->assertEquals($requestData['linkContent']['sample_type'], $link->getSampleType()); + $this->assertEquals($requestData['link']['title'], $link->getTitle()); + $this->assertEquals($requestData['link']['sort_order'], $link->getSortOrder()); + $this->assertEquals($requestData['link']['price'], $link->getPrice()); + $this->assertEquals($requestData['link']['is_shareable'], $link->getIsShareable()); + $this->assertEquals($requestData['link']['number_of_downloads'], $link->getNumberOfDownloads()); + $this->assertEquals($requestData['link']['link_url'], $link->getLinkUrl()); + $this->assertEquals($requestData['link']['link_type'], $link->getLinkType()); + $this->assertEquals($requestData['link']['sample_url'], $link->getSampleUrl()); + $this->assertEquals($requestData['link']['sample_type'], $link->getSampleType()); $this->assertEmpty($globalScopeLink->getTitle()); $this->assertEmpty($globalScopeLink->getPrice()); } @@ -198,11 +199,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link with URL resources', 'sort_order' => 1, 'price' => 10.1, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_url' => 'http://www.example.com/', 'link_type' => 'url', @@ -214,15 +215,15 @@ class LinkRepositoryTest extends WebapiAbstract $newLinkId = $this->_webApiCall($this->createServiceInfo, $requestData); $link = $this->getTargetLink($this->getTargetProduct(), $newLinkId); $this->assertNotNull($link); - $this->assertEquals($requestData['linkContent']['title'], $link->getTitle()); - $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder()); - $this->assertEquals($requestData['linkContent']['price'], $link->getPrice()); - $this->assertEquals($requestData['linkContent']['shareable'], $link->getIsShareable()); - $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads()); - $this->assertEquals($requestData['linkContent']['link_url'], $link->getLinkUrl()); - $this->assertEquals($requestData['linkContent']['link_type'], $link->getLinkType()); - $this->assertEquals($requestData['linkContent']['sample_type'], $link->getSampleType()); - $this->assertEquals($requestData['linkContent']['sample_url'], $link->getSampleUrl()); + $this->assertEquals($requestData['link']['title'], $link->getTitle()); + $this->assertEquals($requestData['link']['sort_order'], $link->getSortOrder()); + $this->assertEquals($requestData['link']['price'], $link->getPrice()); + $this->assertEquals($requestData['link']['is_shareable'], $link->getIsShareable()); + $this->assertEquals($requestData['link']['number_of_downloads'], $link->getNumberOfDownloads()); + $this->assertEquals($requestData['link']['link_url'], $link->getLinkUrl()); + $this->assertEquals($requestData['link']['link_type'], $link->getLinkType()); + $this->assertEquals($requestData['link']['sample_type'], $link->getSampleType()); + $this->assertEquals($requestData['link']['sample_url'], $link->getSampleUrl()); } /** @@ -235,12 +236,15 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link with URL resources', 'sort_order' => 1, 'price' => 10.1, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, + 'link_type' => 'invalid', + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com', ], ]; @@ -257,16 +261,16 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 1, 'price' => 10, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_type' => 'url', 'link_url' => 'http://www.example.com/', 'sample_type' => 'file', - 'sample_file' => [ + 'sample_file_content' => [ 'file_data' => 'not_a_base64_encoded_content', 'name' => 'image.jpg', ], @@ -286,17 +290,19 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 1, 'price' => 10, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_type' => 'file', - 'link_file' => [ + 'link_file_content' => [ 'file_data' => 'not_a_base64_encoded_content', 'name' => 'image.jpg', ], + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/', ], ]; @@ -313,17 +319,19 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Title', 'sort_order' => 15, 'price' => 10, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_type' => 'file', - 'link_file' => [ + 'link_file_content' => [ 'file_data' => base64_encode(file_get_contents($this->testImagePath)), 'name' => 'name/with|forbidden{characters', ], + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/', ], ]; @@ -340,16 +348,16 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 1, 'price' => 10, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_type' => 'url', 'link_url' => 'http://www.example.com/', 'sample_type' => 'file', - 'sample_file' => [ + 'sample_file_content' => [ 'file_data' => base64_encode(file_get_contents($this->testImagePath)), 'name' => 'name/with|forbidden{characters', ], @@ -369,14 +377,16 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 1, 'price' => 10, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'link_type' => 'url', 'link_url' => 'http://example<.>com/', + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/', ], ]; @@ -393,11 +403,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 1, 'price' => 150, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 0, 'sample_type' => 'url', 'sample_url' => 'http://example<.>com/', @@ -420,11 +430,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 1, 'price' => $linkPrice, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 0, 'sample_type' => 'url', 'sample_url' => 'http://example.com/', @@ -442,7 +452,6 @@ class LinkRepositoryTest extends WebapiAbstract public function getInvalidLinkPrice() { return [ - ['string_value'], [-1.5], ]; } @@ -458,11 +467,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => $sortOrder, 'price' => 10, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 0, 'sample_type' => 'url', 'sample_url' => 'http://example.com/', @@ -494,11 +503,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 0, 'price' => 10, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => $numberOfDownloads, 'sample_type' => 'url', 'sample_url' => 'http://example.com/', @@ -530,11 +539,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'simple', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 50, 'price' => 200, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 10, 'sample_type' => 'url', 'sample_url' => 'http://example.com/', @@ -555,11 +564,11 @@ class LinkRepositoryTest extends WebapiAbstract $requestData = [ 'isGlobalScopeContent' => false, 'sku' => 'wrong-sku', - 'linkContent' => [ + 'link' => [ 'title' => 'Link Title', 'sort_order' => 15, 'price' => 200, - 'shareable' => true, + 'is_shareable' => true, 'number_of_downloads' => 100, 'sample_type' => 'url', 'sample_url' => 'http://example.com/', @@ -580,24 +589,26 @@ class LinkRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/{$linkId}"; $requestData = [ 'isGlobalScopeContent' => false, - 'linkId' => $linkId, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ + 'id' => $linkId, 'title' => 'Updated Title', 'sort_order' => 2, 'price' => 100.10, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 50, + 'link_type' => 'url', + 'sample_type' => 'url', ], ]; $this->assertEquals($linkId, $this->_webApiCall($this->updateServiceInfo, $requestData)); $link = $this->getTargetLink($this->getTargetProduct(), $linkId); $this->assertNotNull($link); - $this->assertEquals($requestData['linkContent']['title'], $link->getTitle()); - $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder()); - $this->assertEquals($requestData['linkContent']['price'], $link->getPrice()); - $this->assertEquals($requestData['linkContent']['shareable'], (bool)$link->getIsShareable()); - $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads()); + $this->assertEquals($requestData['link']['title'], $link->getTitle()); + $this->assertEquals($requestData['link']['sort_order'], $link->getSortOrder()); + $this->assertEquals($requestData['link']['price'], $link->getPrice()); + $this->assertEquals($requestData['link']['is_shareable'], (bool)$link->getIsShareable()); + $this->assertEquals($requestData['link']['number_of_downloads'], $link->getNumberOfDownloads()); } /** @@ -611,14 +622,16 @@ class LinkRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/{$linkId}"; $requestData = [ 'isGlobalScopeContent' => true, - 'linkId' => $linkId, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ + 'id' => $linkId, 'title' => 'Updated Title', 'sort_order' => 2, 'price' => 100.10, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 50, + 'link_type' => 'url', + 'sample_type' => 'url', ], ]; @@ -629,11 +642,11 @@ class LinkRepositoryTest extends WebapiAbstract // Title and price were set on store view level in fixture so they must be the same $this->assertEquals($originalLink->getTitle(), $link->getTitle()); $this->assertEquals($originalLink->getPrice(), $link->getPrice()); - $this->assertEquals($requestData['linkContent']['title'], $globalScopeLink->getTitle()); - $this->assertEquals($requestData['linkContent']['price'], $globalScopeLink->getPrice()); - $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder()); - $this->assertEquals($requestData['linkContent']['shareable'], (bool)$link->getIsShareable()); - $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads()); + $this->assertEquals($requestData['link']['title'], $globalScopeLink->getTitle()); + $this->assertEquals($requestData['link']['price'], $globalScopeLink->getPrice()); + $this->assertEquals($requestData['link']['sort_order'], $link->getSortOrder()); + $this->assertEquals($requestData['link']['is_shareable'], (bool)$link->getIsShareable()); + $this->assertEquals($requestData['link']['number_of_downloads'], $link->getNumberOfDownloads()); } /** @@ -645,14 +658,16 @@ class LinkRepositoryTest extends WebapiAbstract $this->updateServiceInfo['rest']['resourcePath'] = '/V1/products/wrong-sku/downloadable-links/1'; $requestData = [ 'isGlobalScopeContent' => true, - 'linkId' => 1, 'sku' => 'wrong-sku', - 'linkContent' => [ + 'link' => [ + 'id' => 1, 'title' => 'Updated Title', 'sort_order' => 2, 'price' => 100.10, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 50, + 'link_type' => 'url', + 'sample_type' => 'url', ], ]; $this->_webApiCall($this->updateServiceInfo, $requestData); @@ -670,14 +685,16 @@ class LinkRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/{$linkId}"; $requestData = [ 'isGlobalScopeContent' => true, - 'linkId' => 9999, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ + 'id' => $linkId, 'title' => 'Title', 'sort_order' => 2, 'price' => 100.10, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 50, + 'link_type' => 'url', + 'sample_type' => 'url', ], ]; @@ -697,14 +714,16 @@ class LinkRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/{$linkId}"; $requestData = [ 'isGlobalScopeContent' => false, - 'linkId' => $linkId, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ + 'id' => $linkId, 'title' => 'Updated Link Title', 'sort_order' => 2, 'price' => $linkPrice, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 50, + 'link_type' => 'url', + 'sample_type' => 'url', ], ]; @@ -724,14 +743,16 @@ class LinkRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/{$linkId}"; $requestData = [ 'isGlobalScopeContent' => false, - 'linkId' => $linkId, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ + 'id' => $linkId, 'title' => 'Updated Link Title', 'sort_order' => $sortOrder, 'price' => 100.50, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => 50, + 'link_type' => 'url', + 'sample_type' => 'url', ], ]; $this->_webApiCall($this->updateServiceInfo, $requestData); @@ -750,14 +771,16 @@ class LinkRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/{$linkId}"; $requestData = [ 'isGlobalScopeContent' => false, - 'linkId' => $linkId, 'sku' => 'downloadable-product', - 'linkContent' => [ + 'link' => [ + 'id' => $linkId, 'title' => 'Updated Link Title', 'sort_order' => 200, 'price' => 100.50, - 'shareable' => false, + 'is_shareable' => false, 'number_of_downloads' => $numberOfDownloads, + 'link_type' => 'url', + 'sample_type' => 'url', ], ]; $this->_webApiCall($this->updateServiceInfo, $requestData); @@ -771,7 +794,7 @@ class LinkRepositoryTest extends WebapiAbstract $linkId = $this->getTargetLink($this->getTargetProduct())->getId(); $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/downloadable-links/{$linkId}"; $requestData = [ - 'linkId' => $linkId, + 'id' => $linkId, ]; $this->assertTrue($this->_webApiCall($this->deleteServiceInfo, $requestData)); @@ -788,7 +811,7 @@ class LinkRepositoryTest extends WebapiAbstract $linkId = 9999; $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/downloadable-links/{$linkId}"; $requestData = [ - 'linkId' => $linkId, + 'id' => $linkId, ]; $this->_webApiCall($this->deleteServiceInfo, $requestData); diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a079eb6d4b6bfa58256a646f396a535c91a0e0cc --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/ProductRepositoryTest.php @@ -0,0 +1,627 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Downloadable\Api; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\Api\ExtensibleDataInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; +use Magento\Bundle\Api\Data\LinkInterface; + +/** + * Class ProductRepositoryTest for testing ProductRepository interface with Downloadable Product + */ +class ProductRepositoryTest extends WebapiAbstract +{ + const SERVICE_NAME = 'catalogProductRepositoryV1'; + const SERVICE_VERSION = 'V1'; + const RESOURCE_PATH = '/V1/products'; + const PRODUCT_SKU = 'sku-test-product-downloadable'; + + /** + * @var string + */ + protected $testImagePath; + + protected function setUp() + { + $this->testImagePath = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'test_image.jpg'; + } + + /** + * Execute per test cleanup + */ + public function tearDown() + { + $this->deleteProductBySku(self::PRODUCT_SKU); + parent::tearDown(); + } + + protected function getLinkData() + { + return [ + 'link1' => [ + 'title' => "link1", + 'sort_order'=> 10, + 'is_shareable' => 1, + 'price' => 2.0, + 'number_of_downloads' => 0, + 'link_type' => 'file', + 'link_file_content' => [ + 'name' => 'link1_content.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + 'sample_type' => 'file', + 'sample_file_content' => [ + 'name' => 'link1_sample.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + ], + 'link2' => [ + 'title' => 'link2', + 'sort_order'=> 20, + 'is_shareable' => 0, + 'price' => 3.0, + 'number_of_downloads' => 100, + 'link_type' => "url", + 'link_url' => 'http://www.example.com/link2.jpg', + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/link2.jpg', + ], + ]; + } + + protected function getExpectedLinkData() + { + return [ + [ + 'title' => 'link1', + 'sort_order' => 10, + 'is_shareable' => 1, + 'price' => 2, + 'number_of_downloads' => 0, + 'link_type' => 'file', + 'sample_type' => 'file', + ], + [ + 'title' => 'link2', + 'sort_order' => 20, + 'is_shareable' => 0, + 'price' => 3, + 'number_of_downloads' => 100, + 'link_type' => 'url', + 'link_url' => 'http://www.example.com/link2.jpg', + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/link2.jpg', + ], + ]; + } + + protected function getSampleData() + { + return [ + 'sample1' => [ + 'title' => 'sample1', + 'sort_order' => 10, + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/sample1.jpg', + ], + 'sample2' => [ + 'title' => 'sample2', + 'sort_order' => 20, + 'sample_type' => 'file', + 'sample_file_content' => [ + 'name' => 'sample2.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + ], + ]; + } + + protected function getExpectedSampleData() + { + return [ + [ + 'title' => 'sample1', + 'sort_order' => 10, + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/sample1.jpg', + ], + [ + 'title' => 'sample2', + 'sort_order' => 20, + 'sample_type' => 'file', + ], + ]; + } + + protected function createDownloadableProduct() + { + $product = [ + "sku" => self::PRODUCT_SKU, + "name" => self::PRODUCT_SKU, + "type_id" => \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE, + "price" => 10, + 'attribute_set_id' => 4, + "extension_attributes" => [ + "downloadable_product_links" => array_values($this->getLinkData()), + "downloadable_product_samples" => array_values($this->getSampleData()), + ], + ]; + + $response = $this->createProduct($product); + $this->assertEquals(self::PRODUCT_SKU, $response[ProductInterface::SKU]); + $this->assertEquals(10, $response['price']); + $this->assertEquals( + \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE, + $response['type_id'] + ); + return $response; + } + + /** + * Create a downloadable product with two links and two samples + */ + public function testCreateDownloadableProduct() + { + $response = $this->createDownloadableProduct(); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]) + ); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]) + ); + $resultLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]; + $this->assertEquals(2, count($resultLinks)); + $this->assertTrue(isset($resultLinks[0]['id'])); + $this->assertTrue(isset($resultLinks[0]['link_file'])); + $this->assertTrue(isset($resultLinks[0]['sample_file'])); + unset($resultLinks[0]['id']); + unset($resultLinks[0]['link_file']); + unset($resultLinks[0]['sample_file']); + $this->assertTrue(isset($resultLinks[1]['id'])); + unset($resultLinks[1]['id']); + + $expectedLinkData = $this->getExpectedLinkData(); + $this->assertEquals($expectedLinkData, $resultLinks); + + $resultSamples = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]; + $this->assertEquals(2, count($resultSamples)); + $this->assertTrue(isset($resultSamples[0]['id'])); + unset($resultSamples[0]['id']); + $this->assertTrue(isset($resultSamples[1]['id'])); + $this->assertTrue(isset($resultSamples[1]['sample_file'])); + unset($resultSamples[1]['sample_file']); + unset($resultSamples[1]['id']); + + $expectedSampleData = $this->getExpectedSampleData(); + $this->assertEquals($expectedSampleData, $resultSamples); + } + + /** + * Update downloadable product, update a link, add two link, delete a link + */ + public function testUpdateDownloadableProductLinks() + { + $response = $this->createDownloadableProduct(); + $resultLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]; + $link1Id = $resultLinks[0]['id']; + $link2Id = $resultLinks[1]['id']; + + $linkFile = $resultLinks[0]['link_file']; + $sampleFile = $resultLinks[0]['sample_file']; + $updatedLink1Data = [ + 'id' => $link1Id, + 'title' => 'link1_updated', + 'sort_order' => 1, //the sort order needs to be smaller than 10 + 'is_shareable' => 0, + 'price' => 5.0, + 'number_of_downloads' => 999, + 'link_type' => 'file', + 'sample_type' => 'file', + 'link_file' => 'http://www.example.com/invalid', //this field will be overridden + 'sample_file' => 'http://www.example.com/invalid', //this field will be overridden + ]; + $linkData = $this->getLinkData(); + + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"] = + [$updatedLink1Data, $linkData['link1'], $linkData['link2']]; + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]); + + $response = $this->saveProduct($response); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]) + ); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]) + ); + $resultLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]; + + $this->assertEquals(3, count($resultLinks)); + $this->assertTrue(isset($resultLinks[0]['id'])); + $this->assertEquals($link1Id, $resultLinks[0]['id']); + $this->assertTrue(isset($resultLinks[0]['link_file'])); + $this->assertEquals($linkFile, $resultLinks[0]['link_file']); + $this->assertTrue(isset($resultLinks[0]['sample_file'])); + $this->assertEquals($sampleFile, $resultLinks[0]['sample_file']); + unset($resultLinks[0]['id']); + unset($resultLinks[0]['link_file']); + unset($resultLinks[0]['sample_file']); + $this->assertTrue(isset($resultLinks[1]['id'])); + $this->assertGreaterThan($link2Id, $resultLinks[1]['id']); + $this->assertTrue(isset($resultLinks[1]['link_file'])); + $this->assertTrue(isset($resultLinks[1]['sample_file'])); + unset($resultLinks[1]['id']); + unset($resultLinks[1]['link_file']); + unset($resultLinks[1]['sample_file']); + $this->assertTrue(isset($resultLinks[2]['id'])); + $this->assertGreaterThan($link2Id, $resultLinks[2]['id']); + unset($resultLinks[2]['id']); + + $expectedLinkData[] = [ + 'title' => 'link1_updated', + 'sort_order' => 1, //the sort order needs to be smaller than 10 + 'is_shareable' => 0, + 'price' => 5.0, + 'number_of_downloads' => 999, + 'link_type' => 'file', + 'sample_type' => 'file', + ]; + $expectedLinkData = array_merge($expectedLinkData, $this->getExpectedLinkData()); + $this->assertEquals($expectedLinkData, $resultLinks); + + $resultSamples = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]; + $this->assertEquals(2, count($resultSamples)); + } + + /** + * Update downloadable product, update two links and change file content + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testUpdateDownloadableProductLinksWithNewFile() + { + $response = $this->createDownloadableProduct(); + $resultLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]; + $link1Id = $resultLinks[0]['id']; + $link2Id = $resultLinks[1]['id']; + + $linkFile = 'link1_content_updated.jpg'; + $sampleFile = 'link1_sample_updated.jpg'; + $updatedLink1Data = [ + 'id' => $link1Id, + 'title' => 'link1_updated', + 'sort_order' => 1, //the sort order needs to be smaller than 10 + 'is_shareable' => 0, + 'price' => 5.0, + 'number_of_downloads' => 999, + 'link_type' => 'file', + 'link_file_content' => [ + 'name' => $linkFile, + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + 'sample_type' => 'file', + 'sample_file_content' => [ + 'name' => $sampleFile, + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + ]; + $updatedLink2Data = [ + 'id' => $link2Id, + 'title' => 'link2_updated', + 'sort_order' => 2, + 'is_shareable' => 0, + 'price' => 6.0, + 'number_of_downloads' => 0, + 'link_type' => 'file', + 'link_file_content' => [ + 'name' => 'link2_content.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + 'sample_type' => 'file', + 'sample_file_content' => [ + 'name' => 'link2_sample.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + ]; + + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"] = + [$updatedLink1Data, $updatedLink2Data]; + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]); + + $response = $this->saveProduct($response); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]) + ); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]) + ); + $resultLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]; + + $this->assertEquals(2, count($resultLinks)); + $this->assertTrue(isset($resultLinks[0]['id'])); + $this->assertEquals($link1Id, $resultLinks[0]['id']); + $this->assertTrue(isset($resultLinks[0]['link_file'])); + $this->assertGreaterThan(0, strpos($resultLinks[0]['link_file'], $linkFile)); + $this->assertTrue(isset($resultLinks[0]['sample_file'])); + $this->assertGreaterThan(0, strpos($resultLinks[0]['sample_file'], $sampleFile)); + unset($resultLinks[0]['id']); + unset($resultLinks[0]['link_file']); + unset($resultLinks[0]['sample_file']); + $this->assertTrue(isset($resultLinks[1]['id'])); + $this->assertEquals($link2Id, $resultLinks[1]['id']); + $this->assertTrue(isset($resultLinks[1]['link_file'])); + $this->assertTrue(isset($resultLinks[1]['sample_file'])); + unset($resultLinks[1]['id']); + unset($resultLinks[1]['link_file']); + unset($resultLinks[1]['sample_file']); + + $expectedLinkData = [ + [ + 'title' => 'link1_updated', + 'sort_order' => 1, //the sort order needs to be smaller than 10 + 'is_shareable' => 0, + 'price' => 5.0, + 'number_of_downloads' => 999, + 'link_type' => 'file', + 'sample_type' => 'file', + ], + [ + 'title' => 'link2_updated', + 'sort_order' => 2, + 'is_shareable' => 0, + 'price' => 6.0, + 'number_of_downloads' => 0, + 'link_type' => 'file', + 'sample_type' => 'file', + 'link_url' => 'http://www.example.com/link2.jpg', //urls are still saved, just not used + 'sample_url' => 'http://www.example.com/link2.jpg', + ] + ]; + $this->assertEquals($expectedLinkData, $resultLinks); + + $resultSamples = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]; + $this->assertEquals(2, count($resultSamples)); + } + + public function testUpdateDownloadableProductSamples() + { + $response = $this->createDownloadableProduct(); + + $resultSample + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]; + $sample1Id = $resultSample[0]['id']; + $sample2Id = $resultSample[1]['id']; + + $updatedSample1Data = [ + 'id' => $sample1Id, + 'title' => 'sample1_updated', + 'sort_order' => 1, + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/sample1.jpg', + ]; + $sampleData = $this->getSampleData(); + + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]); + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"] = + [$updatedSample1Data, $sampleData['sample1'], $sampleData['sample2']]; + + $response = $this->saveProduct($response); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]) + ); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]) + ); + $resultLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]; + + $this->assertEquals(2, count($resultLinks)); + + $resultSamples = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]; + $this->assertEquals(3, count($resultSamples)); + $this->assertTrue(isset($resultSamples[0]['id'])); + $this->assertEquals($sample1Id, $resultSamples[0]['id']); + unset($resultSamples[0]['id']); + $this->assertTrue(isset($resultSamples[1]['id'])); + $this->assertGreaterThan($sample2Id, $resultSamples[1]['id']); + unset($resultSamples[1]['id']); + $this->assertTrue(isset($resultSamples[2]['id'])); + $this->assertGreaterThan($sample2Id, $resultSamples[2]['id']); + $this->assertTrue(isset($resultSamples[2]['sample_file'])); + unset($resultSamples[2]['sample_file']); + unset($resultSamples[2]['id']); + + $expectedSampleData[] = [ + 'title' => 'sample1_updated', + 'sort_order' => 1, + 'sample_type' => 'url', + 'sample_url' => 'http://www.example.com/sample1.jpg', + ]; + $expectedSampleData = array_merge($expectedSampleData, $this->getExpectedSampleData()); + $this->assertEquals($expectedSampleData, $resultSamples); + } + + public function testUpdateDownloadableProductSamplesWithNewFile() + { + $response = $this->createDownloadableProduct(); + + $resultSample + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]; + $sample1Id = $resultSample[0]['id']; + $sample2Id = $resultSample[1]['id']; + + //upload a file for sample 1 + $updatedSample1Data = [ + 'id' => $sample1Id, + 'title' => 'sample1_updated', + 'sort_order' => 1, + 'sample_type' => 'file', + 'sample_file_content' => [ + 'name' => 'sample1.jpg', + 'file_data' => base64_encode(file_get_contents($this->testImagePath)), + ], + ]; + //change title for sample 2 + $updatedSamp2e1Data = [ + 'id' => $sample2Id, + 'title' => 'sample2_updated', + 'sort_order' => 2, + 'sample_type' => 'file', + ]; + + unset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]); + $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"] = + [$updatedSample1Data, $updatedSamp2e1Data]; + + $response = $this->saveProduct($response); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]) + ); + $this->assertTrue( + isset($response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]) + ); + $resultLinks + = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_links"]; + + $this->assertEquals(2, count($resultLinks)); + + $resultSamples = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["downloadable_product_samples"]; + $this->assertEquals(2, count($resultSamples)); + $this->assertTrue(isset($resultSamples[0]['id'])); + $this->assertEquals($sample1Id, $resultSamples[0]['id']); + unset($resultSamples[0]['id']); + $this->assertTrue(isset($resultSamples[0]['sample_file'])); + $this->assertContains('sample1.jpg', $resultSamples[0]['sample_file']); + unset($resultSamples[0]['sample_file']); + $this->assertTrue(isset($resultSamples[1]['id'])); + $this->assertEquals($sample2Id, $resultSamples[1]['id']); + unset($resultSamples[1]['id']); + $this->assertTrue(isset($resultSamples[1]['sample_file'])); + $this->assertContains('sample2.jpg', $resultSamples[1]['sample_file']); + unset($resultSamples[1]['sample_file']); + + $expectedSampleData = [ + [ + 'title' => 'sample1_updated', + 'sort_order' => 1, + 'sample_type' => 'file', + 'sample_url' => 'http://www.example.com/sample1.jpg', + ], + [ + 'title' => 'sample2_updated', + 'sort_order' => 2, + 'sample_type' => 'file', + ], + ]; + $this->assertEquals($expectedSampleData, $resultSamples); + } + + /** + * Get product + * + * @param string $productSku + * @return array the product data + */ + protected function getProduct($productSku) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $productSku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Get', + ], + ]; + + $response = (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ? + $this->_webApiCall($serviceInfo, ['sku' => $productSku]) : $this->_webApiCall($serviceInfo); + + return $response; + } + + /** + * Create product + * + * @param array $product + * @return array the created product data + */ + protected function createProduct($product) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } + + /** + * Delete a product by sku + * + * @param $productSku + * @return bool + */ + protected function deleteProductBySku($productSku) + { + $resourcePath = self::RESOURCE_PATH . '/' . $productSku; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $resourcePath, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'deleteById', + ], + ]; + $requestData = ["sku" => $productSku]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } + + /** + * Save product + * + * @param array $product + * @return array the created product data + */ + protected function saveProduct($product) + { + $resourcePath = self::RESOURCE_PATH . '/' . $product['sku']; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $resourcePath, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php index c4fe8606cb8bc9f680e3db3da0bdc4061941a05c..0a1bba69a89890b7feeec2afd84a793181e2d239 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php @@ -79,9 +79,11 @@ class SampleRepositoryTest extends WebapiAbstract */ protected function getTargetProduct($isScopeGlobal = false) { - $product = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\ProductFactory')->create()->load(1); if ($isScopeGlobal) { - $product->setStoreId(0); + $product = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\ProductFactory') + ->create()->setStoreId(0)->load(1); + } else { + $product = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\ProductFactory')->create()->load(1); } return $product; @@ -120,11 +122,11 @@ class SampleRepositoryTest extends WebapiAbstract { $requestData = [ 'isGlobalScopeContent' => true, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Title', 'sort_order' => 1, - 'sample_file' => [ + 'sample_file_content' => [ 'file_data' => base64_encode(file_get_contents($this->testImagePath)), 'name' => 'image.jpg', ], @@ -136,10 +138,11 @@ class SampleRepositoryTest extends WebapiAbstract $globalScopeSample = $this->getTargetSample($this->getTargetProduct(true), $newSampleId); $sample = $this->getTargetSample($this->getTargetProduct(), $newSampleId); $this->assertNotNull($sample); - $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle()); - $this->assertEquals($requestData['sampleContent']['title'], $globalScopeSample->getTitle()); - $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder()); - $this->assertEquals($requestData['sampleContent']['sample_type'], $sample->getSampleType()); + $this->assertNotNull($sample->getId()); + $this->assertEquals($requestData['sample']['title'], $sample->getTitle()); + $this->assertEquals($requestData['sample']['title'], $globalScopeSample->getTitle()); + $this->assertEquals($requestData['sample']['sort_order'], $sample->getSortOrder()); + $this->assertEquals($requestData['sample']['sample_type'], $sample->getSampleType()); $this->assertStringEndsWith('.jpg', $sample->getSampleFile()); $this->assertNull($sample->getSampleUrl()); } @@ -151,8 +154,8 @@ class SampleRepositoryTest extends WebapiAbstract { $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Store View Title', 'sort_order' => 1, 'sample_url' => 'http://www.sample.example.com/', @@ -164,10 +167,10 @@ class SampleRepositoryTest extends WebapiAbstract $sample = $this->getTargetSample($this->getTargetProduct(), $newSampleId); $globalScopeSample = $this->getTargetSample($this->getTargetProduct(true), $newSampleId); $this->assertNotNull($sample); - $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle()); - $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder()); - $this->assertEquals($requestData['sampleContent']['sample_url'], $sample->getSampleUrl()); - $this->assertEquals($requestData['sampleContent']['sample_type'], $sample->getSampleType()); + $this->assertEquals($requestData['sample']['title'], $sample->getTitle()); + $this->assertEquals($requestData['sample']['sort_order'], $sample->getSortOrder()); + $this->assertEquals($requestData['sample']['sample_url'], $sample->getSampleUrl()); + $this->assertEquals($requestData['sample']['sample_type'], $sample->getSampleType()); $this->assertEmpty($globalScopeSample->getTitle()); } @@ -178,8 +181,8 @@ class SampleRepositoryTest extends WebapiAbstract { $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Sample with URL resource', 'sort_order' => 1, 'sample_url' => 'http://www.sample.example.com/', @@ -190,10 +193,10 @@ class SampleRepositoryTest extends WebapiAbstract $newSampleId = $this->_webApiCall($this->createServiceInfo, $requestData); $sample = $this->getTargetSample($this->getTargetProduct(), $newSampleId); $this->assertNotNull($sample); - $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle()); - $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder()); - $this->assertEquals($requestData['sampleContent']['sample_type'], $sample->getSampleType()); - $this->assertEquals($requestData['sampleContent']['sample_url'], $sample->getSampleUrl()); + $this->assertEquals($requestData['sample']['title'], $sample->getTitle()); + $this->assertEquals($requestData['sample']['sort_order'], $sample->getSortOrder()); + $this->assertEquals($requestData['sample']['sample_type'], $sample->getSampleType()); + $this->assertEquals($requestData['sample']['sample_url'], $sample->getSampleUrl()); } /** @@ -201,14 +204,15 @@ class SampleRepositoryTest extends WebapiAbstract * @expectedException \Exception * @expectedExceptionMessage Invalid sample type. */ - public function testCreateThrowsExceptionIfSampleTypeIsNotSpecified() + public function testCreateThrowsExceptionIfSampleTypeIsInvalid() { $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Sample with URL resource', 'sort_order' => 1, + 'sample_type' => 'invalid', ], ]; @@ -224,12 +228,12 @@ class SampleRepositoryTest extends WebapiAbstract { $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Sample Title', 'sort_order' => 1, 'sample_type' => 'file', - 'sample_file' => [ + 'sample_file_content' => [ 'file_data' => 'not_a_base64_encoded_content', 'name' => 'image.jpg', ], @@ -248,12 +252,12 @@ class SampleRepositoryTest extends WebapiAbstract { $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Title', 'sort_order' => 15, 'sample_type' => 'file', - 'sample_file' => [ + 'sample_file_content' => [ 'file_data' => base64_encode(file_get_contents($this->testImagePath)), 'name' => 'name/with|forbidden{characters', ], @@ -272,8 +276,8 @@ class SampleRepositoryTest extends WebapiAbstract { $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Sample Title', 'sort_order' => 1, 'sample_type' => 'url', @@ -294,8 +298,8 @@ class SampleRepositoryTest extends WebapiAbstract { $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ 'title' => 'Sample Title', 'sort_order' => $sortOrder, 'sample_type' => 'url', @@ -325,8 +329,8 @@ class SampleRepositoryTest extends WebapiAbstract $this->createServiceInfo['rest']['resourcePath'] = '/V1/products/simple/downloadable-links/samples'; $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'simple', - 'sampleContent' => [ + 'sku' => 'simple', + 'sample' => [ 'title' => 'Sample Title', 'sort_order' => 50, 'sample_type' => 'url', @@ -345,8 +349,8 @@ class SampleRepositoryTest extends WebapiAbstract $this->createServiceInfo['rest']['resourcePath'] = '/V1/products/wrong-sku/downloadable-links/samples'; $requestData = [ 'isGlobalScopeContent' => false, - 'productSku' => 'wrong-sku', - 'sampleContent' => [ + 'sku' => 'wrong-sku', + 'sample' => [ 'title' => 'Title', 'sort_order' => 15, 'sample_type' => 'url', @@ -366,19 +370,21 @@ class SampleRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}"; $requestData = [ 'isGlobalScopeContent' => false, - 'sampleId' => $sampleId, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ + 'id' => $sampleId, 'title' => 'Updated Title', 'sort_order' => 2, + 'sample_type' => 'url', ], ]; $this->assertEquals($sampleId, $this->_webApiCall($this->updateServiceInfo, $requestData)); $sample = $this->getTargetSample($this->getTargetProduct(), $sampleId); $this->assertNotNull($sample); - $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle()); - $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder()); + $this->assertEquals($requestData['sample']['id'], $sample->getId()); + $this->assertEquals($requestData['sample']['title'], $sample->getTitle()); + $this->assertEquals($requestData['sample']['sort_order'], $sample->getSortOrder()); } /** @@ -392,11 +398,12 @@ class SampleRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}"; $requestData = [ 'isGlobalScopeContent' => true, - 'sampleId' => $sampleId, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ + 'id' => $sampleId, 'title' => 'Updated Title', 'sort_order' => 2, + 'sample_type' => 'url', ], ]; @@ -406,8 +413,8 @@ class SampleRepositoryTest extends WebapiAbstract $this->assertNotNull($sample); // Title was set on store view level in fixture so it must be the same $this->assertEquals($originalSample->getTitle(), $sample->getTitle()); - $this->assertEquals($requestData['sampleContent']['title'], $globalScopeSample->getTitle()); - $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder()); + $this->assertEquals($requestData['sample']['title'], $globalScopeSample->getTitle()); + $this->assertEquals($requestData['sample']['sort_order'], $sample->getSortOrder()); } /** @@ -419,11 +426,12 @@ class SampleRepositoryTest extends WebapiAbstract $this->updateServiceInfo['rest']['resourcePath'] = '/V1/products/wrong-sku/downloadable-links/samples/1'; $requestData = [ 'isGlobalScopeContent' => true, - 'sampleId' => 1, - 'productSku' => 'wrong-sku', - 'sampleContent' => [ + 'sku' => 'wrong-sku', + 'sample' => [ + 'id' => 1, 'title' => 'Updated Title', 'sort_order' => 2, + 'sample_type' => 'url', ], ]; $this->_webApiCall($this->updateServiceInfo, $requestData); @@ -441,11 +449,12 @@ class SampleRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}"; $requestData = [ 'isGlobalScopeContent' => true, - 'sampleId' => 9999, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ + 'id' => $sampleId, 'title' => 'Title', 'sort_order' => 2, + 'sample_type' => 'url', ], ]; @@ -465,11 +474,12 @@ class SampleRepositoryTest extends WebapiAbstract = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}"; $requestData = [ 'isGlobalScopeContent' => false, - 'sampleId' => $sampleId, - 'productSku' => 'downloadable-product', - 'sampleContent' => [ + 'sku' => 'downloadable-product', + 'sample' => [ + 'id' => $sampleId, 'title' => 'Updated Sample Title', 'sort_order' => $sortOrder, + 'sample_type' => 'url', ], ]; $this->_webApiCall($this->updateServiceInfo, $requestData); @@ -483,7 +493,7 @@ class SampleRepositoryTest extends WebapiAbstract $sampleId = $this->getTargetSample($this->getTargetProduct())->getId(); $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/downloadable-links/samples/{$sampleId}"; $requestData = [ - 'sampleId' => $sampleId, + 'id' => $sampleId, ]; $this->assertTrue($this->_webApiCall($this->deleteServiceInfo, $requestData)); @@ -500,7 +510,7 @@ class SampleRepositoryTest extends WebapiAbstract $sampleId = 9999; $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/downloadable-links/samples/{$sampleId}"; $requestData = [ - 'sampleId' => $sampleId, + 'id' => $sampleId, ]; $this->_webApiCall($this->deleteServiceInfo, $requestData); diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c8ab24527c633a12fd46442a9528570a4586e458 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php @@ -0,0 +1,203 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\GroupedProduct\Api; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\TestFramework\TestCase\WebapiAbstract; + +class ProductRepositoryInterfaceTest extends WebapiAbstract +{ + const SERVICE_NAME = 'catalogProductRepositoryV1'; + const SERVICE_VERSION = 'V1'; + const RESOURCE_PATH = '/V1/products'; + + /** + * Get Product + * + * @param $sku + * @return ProductInterface + */ + protected function getProduct($sku) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Get', + ], + ]; + + $response = $this->_webApiCall($serviceInfo, ['sku' => $sku]); + return $response; + } + + /** + * Update Product + * + * @param $product + * @return mixed + */ + protected function updateProduct($product) + { + $sku = $product[ProductInterface::SKU]; + if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) { + $product[ProductInterface::SKU] = null; + } + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + $response = $this->_webApiCall($serviceInfo, $requestData); + return $response; + } + + /** + * Save Product + * + * @param $product + * @return mixed + */ + protected function saveProduct($product) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + $requestData = ['product' => $product]; + return $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * Delete Product + * + * @param string $sku + * @return boolean + */ + protected function deleteProduct($sku) + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'DeleteById', + ], + ]; + + return (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ? + $this->_webApiCall($serviceInfo, ['sku' => $sku]) : $this->_webApiCall($serviceInfo); + } + + public function testProductLinks() + { + // Create simple product + $productData = [ + ProductInterface::SKU => "product_simple_500", + ProductInterface::NAME => "Product Simple 500", + ProductInterface::VISIBILITY => 4, + ProductInterface::TYPE_ID => 'simple', + ProductInterface::PRICE => 100, + ProductInterface::STATUS => 1, + ProductInterface::TYPE_ID => 'simple', + ProductInterface::ATTRIBUTE_SET_ID => 4, + ]; + + $this->saveProduct($productData); + + // Create a group product + $productLinkData = ["product_sku" => "group_product_500", "link_type" => "associated", + "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", + "position" => 0, "extension_attributes" => ["qty" => 1]]; + $productWithGroupData = [ + ProductInterface::SKU => "group_product_500", + ProductInterface::NAME => "Group Product 500", + ProductInterface::VISIBILITY => 4, + ProductInterface::TYPE_ID => 'grouped', + ProductInterface::PRICE => 300, + ProductInterface::STATUS => 1, + ProductInterface::ATTRIBUTE_SET_ID => 4, + "product_links" => [$productLinkData] + ]; + + $this->saveProduct($productWithGroupData); + $response = $this->getProduct("group_product_500"); + $this->assertArrayHasKey('product_links', $response); + $links = $response['product_links']; + $this->assertEquals(1, count($links)); + $this->assertEquals($productLinkData, $links[0]); + + // update link information for Group Product + $productLinkData1 = ["product_sku" => "group_product_500", "link_type" => "associated", + "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", + "position" => 0, "extension_attributes" => ["qty" => 4]]; + $productLinkData2 = ["product_sku" => "group_product_500", "link_type" => "upsell", + "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", + "position" => 0, "extension_attributes" => []]; + $productWithGroupData = [ + ProductInterface::SKU => "group_product_500", + ProductInterface::NAME => "Group Product 500", + ProductInterface::VISIBILITY => 4, + ProductInterface::TYPE_ID => 'grouped', + ProductInterface::PRICE => 300, + ProductInterface::STATUS => 1, + ProductInterface::ATTRIBUTE_SET_ID => 4, + "product_links" => [$productLinkData1, $productLinkData2] + ]; + + $this->saveProduct($productWithGroupData); + $response = $this->getProduct("group_product_500"); + + $this->assertArrayHasKey('product_links', $response); + $links = $response['product_links']; + $this->assertEquals(2, count($links)); + $this->assertEquals($productLinkData1, $links[1]); + $this->assertEquals($productLinkData2, $links[0]); + + // Remove link + $productWithNoLinkData = [ + ProductInterface::SKU => "group_product_500", + ProductInterface::NAME => "Group Product 500", + ProductInterface::VISIBILITY => 4, + ProductInterface::TYPE_ID => 'grouped', + ProductInterface::PRICE => 300, + ProductInterface::STATUS => 1, + ProductInterface::ATTRIBUTE_SET_ID => 4, + "product_links" => [] + ]; + + $this->saveProduct($productWithNoLinkData); + $response = $this->getProduct("group_product_500"); + $this->assertArrayHasKey('product_links', $response); + $links = $response['product_links']; + $this->assertEquals([], $links); + + $this->deleteProduct("product_simple_500"); + $this->deleteProduct("group_product_500"); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxClassRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxClassRepositoryTest.php index 1557278ce1bb31a76ac96d90a90c57b6bada4d21..2d20a4e9110939aa3c8298b8eb6e317436bf2454 100644 --- a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxClassRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxClassRepositoryTest.php @@ -12,6 +12,7 @@ use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Tax\Api\Data\TaxClassInterfaceFactory; +use Magento\Tax\Model\ClassModel; use Magento\Tax\Model\ClassModelRegistry; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; @@ -171,9 +172,9 @@ class TaxClassRepositoryTest extends WebapiAbstract ]; $requestData = ['taxClassId' => $taxClassId]; $taxClassData = $this->_webApiCall($serviceInfo, $requestData); - $this->assertEquals($taxClassData[Data\TaxClassInterface::KEY_NAME], $taxClassName); + $this->assertEquals($taxClassData[ClassModel::KEY_NAME], $taxClassName); $this->assertEquals( - $taxClassData[Data\TaxClassInterface::KEY_TYPE], + $taxClassData[ClassModel::KEY_TYPE], TaxClassManagementInterface::TYPE_CUSTOMER ); } @@ -220,7 +221,7 @@ class TaxClassRepositoryTest extends WebapiAbstract public function testSearchTaxClass() { $taxClassName = 'Retail Customer'; - $taxClassNameField = Data\TaxClassInterface::KEY_NAME; + $taxClassNameField = ClassModel::KEY_NAME; $filter = $this->filterBuilder->setField($taxClassNameField) ->setValue($taxClassName) ->create(); @@ -249,23 +250,23 @@ class TaxClassRepositoryTest extends WebapiAbstract public function testSearchTaxClassMultipleFilterGroups() { $productTaxClass = [ - Data\TaxClassInterface::KEY_NAME => 'Taxable Goods', - Data\TaxClassInterface::KEY_TYPE => 'PRODUCT', + ClassModel::KEY_NAME => 'Taxable Goods', + ClassModel::KEY_TYPE => 'PRODUCT', ]; - $customerTaxClass = [Data\TaxClassInterface::KEY_NAME => 'Retail Customer', - Data\TaxClassInterface::KEY_TYPE => 'CUSTOMER', ]; + $customerTaxClass = [ClassModel::KEY_NAME => 'Retail Customer', + ClassModel::KEY_TYPE => 'CUSTOMER', ]; - $filter1 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_NAME) - ->setValue($productTaxClass[Data\TaxClassInterface::KEY_NAME]) + $filter1 = $this->filterBuilder->setField(ClassModel::KEY_NAME) + ->setValue($productTaxClass[ClassModel::KEY_NAME]) ->create(); - $filter2 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_NAME) - ->setValue($customerTaxClass[Data\TaxClassInterface::KEY_NAME]) + $filter2 = $this->filterBuilder->setField(ClassModel::KEY_NAME) + ->setValue($customerTaxClass[ClassModel::KEY_NAME]) ->create(); - $filter3 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_TYPE) - ->setValue($productTaxClass[Data\TaxClassInterface::KEY_TYPE]) + $filter3 = $this->filterBuilder->setField(ClassModel::KEY_TYPE) + ->setValue($productTaxClass[ClassModel::KEY_TYPE]) ->create(); - $filter4 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_TYPE) - ->setValue($customerTaxClass[Data\TaxClassInterface::KEY_TYPE]) + $filter4 = $this->filterBuilder->setField(ClassModel::KEY_TYPE) + ->setValue($customerTaxClass[ClassModel::KEY_TYPE]) ->create(); /** @@ -291,12 +292,12 @@ class TaxClassRepositoryTest extends WebapiAbstract $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(2, $searchResults['total_count']); $this->assertEquals( - $productTaxClass[Data\TaxClassInterface::KEY_NAME], - $searchResults['items'][0][Data\TaxClassInterface::KEY_NAME] + $productTaxClass[ClassModel::KEY_NAME], + $searchResults['items'][0][ClassModel::KEY_NAME] ); $this->assertEquals( - $customerTaxClass[Data\TaxClassInterface::KEY_NAME], - $searchResults['items'][1][Data\TaxClassInterface::KEY_NAME] + $customerTaxClass[ClassModel::KEY_NAME], + $searchResults['items'][1][ClassModel::KEY_NAME] ); /** class_name == 'Retail Customer' && ( class_type == 'CUSTOMER' || class_type == 'PRODUCT') */ @@ -309,8 +310,8 @@ class TaxClassRepositoryTest extends WebapiAbstract $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(1, $searchResults['total_count']); $this->assertEquals( - $customerTaxClass[Data\TaxClassInterface::KEY_NAME], - $searchResults['items'][0][Data\TaxClassInterface::KEY_NAME] + $customerTaxClass[ClassModel::KEY_NAME], + $searchResults['items'][0][ClassModel::KEY_NAME] ); } } diff --git a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php index 9f47505721b8f6bb1e4b403e6b2f56b861fd3668..a140347e2498fe75163c9822a4f5f8eb80fd9506 100644 --- a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php @@ -10,7 +10,7 @@ use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteria; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SortOrderBuilder; -use Magento\Tax\Api\Data\TaxRateInterface as TaxRate; +use Magento\Tax\Model\Calculation\Rate; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; @@ -433,7 +433,7 @@ class TaxRateRepositoryTest extends WebapiAbstract $rates = $this->setupTaxRatesForSearch(); // Find rates whose code is 'codeUs12' - $filter = $this->filterBuilder->setField(TaxRate::KEY_CODE) + $filter = $this->filterBuilder->setField(Rate::KEY_CODE) ->setValue('codeUs12') ->create(); @@ -480,11 +480,11 @@ class TaxRateRepositoryTest extends WebapiAbstract $rates = $this->setupTaxRatesForSearch(); // Find rates which country id 'CZ' - $filter = $this->filterBuilder->setField(TaxRate::KEY_COUNTRY_ID) + $filter = $this->filterBuilder->setField(Rate::KEY_COUNTRY_ID) ->setValue('CZ') ->create(); $sortOrder = $this->sortOrderBuilder - ->setField(TaxRate::KEY_POSTCODE) + ->setField(Rate::KEY_POSTCODE) ->setDirection(SearchCriteria::SORT_DESC) ->create(); // Order them by descending postcode (not the default order) diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php index 41d6e8a2914deb9a863b42d2634d0c9aab934324..a64744df17ad68e016255d6d2396bad4e59564f6 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php @@ -81,7 +81,7 @@ class RestErrorHandlingTest extends \Magento\TestFramework\TestCase\WebapiAbstra { $serviceInfo = [ 'rest' => [ - 'resourcePath' => '/V1/errortest/otherexception', + 'resourcePath' => '/V1/errortest/otherException', 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, ], ]; diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php index 8b04e6bd56c8408b7af23580dd19600adae5d53e..d805ea841654d68eed204e683be0d18bf194b5d1 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/ConditionsElement.php @@ -11,8 +11,7 @@ use Magento\Mtf\Client\Locator; use Magento\Mtf\Client\ElementInterface; /** - * Class ConditionsElement - * Typified element class for conditions + * Typified element class for conditions. * * Format value. * Add slash to symbols: "{", "}", "[", "]", ":". @@ -39,77 +38,110 @@ use Magento\Mtf\Client\ElementInterface; class ConditionsElement extends SimpleElement { /** - * Main condition + * Count for trying fill condition element. + */ + const TRY_COUNT = 3; + + /** + * Main condition. * * @var string */ protected $mainCondition = './/ul[contains(@id,"__1__children")]/..'; /** - * Identification for chooser grid + * Identification for chooser grid. * * @var string */ protected $chooserLocator = '.rule-chooser-trigger'; /** - * Button add condition + * Button add condition. * * @var string */ protected $addNew = './/*[contains(@class,"rule-param-new-child")]/a'; /** - * Button remove condition + * Button remove condition. * * @var string */ protected $remove = './/*/a[@class="rule-param-remove"]'; /** - * New condition + * New condition. * * @var string */ protected $newCondition = './ul/li/span[contains(@class,"rule-param-new-child")]/..'; /** - * Type of new condition + * Type of new condition. * * @var string */ protected $typeNew = './/*[@class="element"]/select'; /** - * Created condition + * Created condition. * * @var string */ protected $created = './ul/li[span[contains(@class,"rule-param-new-child")]]/preceding-sibling::li[1]'; /** - * Children condition + * Children condition. * * @var string */ protected $children = './/ul[contains(@id,"conditions__")]'; /** - * Parameter of condition + * Parameter of condition. * * @var string */ protected $param = './span[span[*[substring(@id,(string-length(@id)-%d+1))="%s"]]]'; /** - * Key of last find param + * Rule param wait locator. + * + * @var string + */ + protected $ruleParamWait = './/*[@class="rule-param-wait"]'; + + /** + * Rule param input selector. + * + * @var string + */ + protected $ruleParamInput = '[name^="rule"]'; + + /** + * Apply rule param link. + * + * @var string + */ + protected $applyRuleParam = './/*[@class="rule-param-apply"]'; + + /** + * Chooser grid locator. + * + * @var string + */ + protected $chooserGridLocator = 'div[id*=chooser]'; + + /** + * Key of last find param. * * @var int */ protected $findKeyParam = 0; /** - * Map of parameters + * Map of parameters. * * @var array */ @@ -122,7 +154,7 @@ class ConditionsElement extends SimpleElement ]; /** - * Map encode special chars + * Map encode special chars. * * @var array */ @@ -135,7 +167,7 @@ class ConditionsElement extends SimpleElement ]; /** - * Map decode special chars + * Map decode special chars. * * @var array */ @@ -148,34 +180,22 @@ class ConditionsElement extends SimpleElement ]; /** - * Rule param wait locator - * - * @var string - */ - protected $ruleParamWait = './/*[@class="rule-param-wait"]'; - - /** - * Chooser grid locator - * - * @var string - */ - protected $chooserGridLocator = 'div[id*=chooser]'; - - /** - * Rule param input selector. + * Latest occurred exception. * - * @var string + * @var \Exception */ - protected $ruleParamInput = '.element [name^="rule"]'; + protected $exception; /** - * Set value to conditions + * Set value to conditions. * * @param string $value * @return void */ public function setValue($value) { + $this->eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]); + $conditions = $this->decodeValue($value); $context = $this->find($this->mainCondition, Locator::SELECTOR_XPATH); $this->clear(); @@ -183,7 +203,7 @@ class ConditionsElement extends SimpleElement } /** - * Add condition combination + * Add conditions combination. * * @param string $condition * @param ElementInterface $context @@ -192,15 +212,7 @@ class ConditionsElement extends SimpleElement protected function addConditionsCombination($condition, ElementInterface $context) { $condition = $this->parseCondition($condition); - - $this->driver->selectWindow(); - $newCondition = $context->find($this->newCondition, Locator::SELECTOR_XPATH); - $newCondition->find($this->addNew, Locator::SELECTOR_XPATH)->click(); - - $this->driver->selectWindow(); - $typeNewCondition = $newCondition->find($this->typeNew, Locator::SELECTOR_XPATH, 'select'); - $typeNewCondition->setValue($condition['type']); - + $this->addCondition($condition['type'], $context); $createdCondition = $context->find($this->created, Locator::SELECTOR_XPATH); $this->waitForCondition($createdCondition); if (!empty($condition['rules'])) { @@ -210,7 +222,7 @@ class ConditionsElement extends SimpleElement } /** - * Add conditions + * Add conditions. * * @param array $conditions * @param ElementInterface $context @@ -229,7 +241,7 @@ class ConditionsElement extends SimpleElement } /** - * Add single Condition + * Add single Condition. * * @param string $condition * @param ElementInterface $context @@ -238,36 +250,55 @@ class ConditionsElement extends SimpleElement protected function addSingleCondition($condition, ElementInterface $context) { $condition = $this->parseCondition($condition); + $this->addCondition($condition['type'], $context); + $createdCondition = $context->find($this->created, Locator::SELECTOR_XPATH); + $this->waitForCondition($createdCondition); + $this->fillCondition($condition['rules'], $createdCondition); + } - $this->driver->selectWindow(); + /** + * Click to add condition button and set type. + * + * @param string $type + * @param ElementInterface $context + * @return void + * @throws \Exception + */ + protected function addCondition($type, ElementInterface $context) + { $newCondition = $context->find($this->newCondition, Locator::SELECTOR_XPATH); - $newCondition->find($this->addNew, Locator::SELECTOR_XPATH)->click(); - - $typeNew = $this->typeNew; - $newCondition->waitUntil( - function () use ($newCondition, $typeNew) { - $element = $newCondition->find($typeNew, Locator::SELECTOR_XPATH, 'select'); - if ($element->isVisible()) { - return true; - } - $this->driver->selectWindow(); - return null; + $count = 0; + + do { + $newCondition->find($this->addNew, Locator::SELECTOR_XPATH)->click(); + + try { + $newCondition->find($this->typeNew, Locator::SELECTOR_XPATH, 'select')->setValue($type); + $isSetType = true; + } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { + $isSetType = false; + $this->exception = $e; + $this->eventManager->dispatchEvent(['exception'], [__METHOD__, $this->getAbsoluteSelector()]); } - ); - $newCondition->find($this->typeNew, Locator::SELECTOR_XPATH, 'select')->setValue($condition['type']); + $count++; + } while (!$isSetType && $count < self::TRY_COUNT); - $createdCondition = $context->find($this->created, Locator::SELECTOR_XPATH); - $this->waitForCondition($createdCondition); - $this->fillCondition($condition['rules'], $createdCondition); + if (!$isSetType) { + $exception = $this->exception ? $this->exception : (new \Exception("Can not add condition: {$type}")); + throw $exception; + } } /** - * Fill single condition + * Fill single condition. * * @param array $rules * @param ElementInterface $element * @return void * @throws \Exception + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function fillCondition(array $rules, ElementInterface $element) { @@ -275,52 +306,117 @@ class ConditionsElement extends SimpleElement foreach ($rules as $rule) { /** @var ElementInterface $param */ $param = $this->findNextParam($element); + $isSet = false; + $count = 0; + + do { + try { + $openParamLink = $param->find('a'); + if ($openParamLink->isVisible()) { + $openParamLink->click(); + } + $this->waitUntil(function () use ($param) { + return $param->find($this->ruleParamInput)->isVisible() ? true : null; + }); + + if ($this->fillGrid($rule, $param)) { + $isSet = true; + } elseif ($this->fillSelect($rule, $param)) { + $isSet = true; + } elseif ($this->fillText($rule, $param)) { + $isSet = true; + } + } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { + $isSet = false; + $this->exception = $e; + $this->eventManager->dispatchEvent(['exception'], [__METHOD__, $this->getAbsoluteSelector()]); + } + $count++; + } while (!$isSet && $count < self::TRY_COUNT); - $this->driver->selectWindow(); - $param->find('a')->click(); - - if (preg_match('`%(.*?)%`', $rule, $chooserGrid)) { - $chooserConfig = explode('#', $chooserGrid[1]); - $param->find($this->chooserLocator)->click(); - $rule = preg_replace('`%(.*?)%`', '', $rule); - $grid = ObjectManager::getInstance()->create( - str_replace('/', '\\', $chooserConfig[0]), - [ - 'element' => $this->find($this->chooserGridLocator) - ] - ); - $grid->searchAndSelect([$chooserConfig[1] => $rule]); - continue; + if (!$isSet) { + $exception = $this->exception ? $this->exception : (new \Exception('Can not set value: ' . $rule)); + throw $exception; } - $input = $this->ruleParamInput; - $param->waitUntil( - function () use ($param, $input) { - $element = $param->find($input); - return $element->isVisible() ? true : null; - } + } + } + + /** + * Fill grid element. + * + * @param string $rule + * @param ElementInterface $param + * @return bool + */ + protected function fillGrid($rule, ElementInterface $param) + { + if (preg_match('`%(.*?)%`', $rule, $chooserGrid)) { + $chooserConfig = explode('#', $chooserGrid[1]); + $rule = preg_replace('`%(.*?)%`', '', $rule); + + $param->find($this->chooserLocator)->click(); + $grid = ObjectManager::getInstance()->create( + str_replace('/', '\\', $chooserConfig[0]), + [ + 'element' => $this->find($this->chooserGridLocator) + ] ); - $value = $param->find('select', Locator::SELECTOR_TAG_NAME, 'select'); - if ($value->isVisible()) { - $value->setValue($rule); - $this->click(); - continue; + $grid->searchAndSelect([$chooserConfig[1] => $rule]); + + $apply = $param->find($this->applyRuleParam, Locator::SELECTOR_XPATH); + if ($apply->isVisible()) { + $apply->click(); } - $value = $param->find('input', Locator::SELECTOR_TAG_NAME); - if ($value->isVisible()) { - $value->setValue($rule); - $apply = $param->find('.//*[@class="rule-param-apply"]', Locator::SELECTOR_XPATH); - if ($apply->isVisible()) { - $apply->click(); - } - continue; + return true; + } + return false; + } + + /** + * Fill select element. + * + * @param string $rule + * @param ElementInterface $param + * @return bool + */ + protected function fillSelect($rule, ElementInterface $param) + { + $value = $param->find('select', Locator::SELECTOR_TAG_NAME, 'select'); + if ($value->isVisible()) { + $value->setValue($rule); + $this->click(); + + return true; + } + return false; + } + + /** + * Fill text element. + * + * @param string $rule + * @param ElementInterface $param + * @return bool + */ + protected function fillText($rule, ElementInterface $param) + { + $value = $param->find('input', Locator::SELECTOR_TAG_NAME); + if ($value->isVisible()) { + $value->setValue($rule); + + $apply = $param->find('.//*[@class="rule-param-apply"]', Locator::SELECTOR_XPATH); + if ($apply->isVisible()) { + $apply->click(); } - throw new \Exception('Undefined type of value '); + + return true; } + return false; } /** - * Decode value + * Decode value. * * @param string $value * @return array @@ -344,7 +440,7 @@ class ConditionsElement extends SimpleElement } /** - * Parse condition + * Parse condition. * * @param string $condition * @return array @@ -366,7 +462,7 @@ class ConditionsElement extends SimpleElement } /** - * Find next param of condition for fill + * Find next param of condition for fill. * * @param ElementInterface $context * @return ElementInterface @@ -387,7 +483,7 @@ class ConditionsElement extends SimpleElement } /** - * Reset key of last find param + * Reset key of last find param. * * @return void */ @@ -397,25 +493,21 @@ class ConditionsElement extends SimpleElement } /** - * Param wait loader + * Param wait loader. * - * @return void + * @param ElementInterface $element */ protected function waitForCondition(ElementInterface $element) { $this->waitUntil( function () use ($element) { - if ($element->getAttribute('class') == 'rule-param-wait') { - $this->driver->selectWindow(); - return null; - } - return true; + return $element->getAttribute('class') == 'rule-param-wait' ? null : true; } ); } /** - * Clear conditions + * Clear conditions. * * @return void */ @@ -429,7 +521,7 @@ class ConditionsElement extends SimpleElement } /** - * Get value from conditions + * Get value from conditions. * * @return null */ diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/LiselectstoreElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/LiselectstoreElement.php index 5d3f79b515b8d7c140a7221c49b7977cbafeef82..5df3f333d46ed0297873f0c650ab387ab7f660ff 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/LiselectstoreElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/LiselectstoreElement.php @@ -65,7 +65,7 @@ class LiselectstoreElement extends SimpleElement public function setValue($value) { $this->eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]); - $this->driver->find($this->toggleSelector)->click(); + $this->context->find($this->toggleSelector)->click(); $value = explode('/', $value); $optionSelector = []; @@ -88,7 +88,7 @@ class LiselectstoreElement extends SimpleElement */ protected function getLiElements() { - $this->driver->find($this->toggleSelector)->click(); + $this->find($this->toggleSelector)->click(); $elements = $this->driver->getElements($this, 'li', Locator::SELECTOR_TAG_NAME); $dropdownData = []; foreach ($elements as $element) { diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php index 6685ac3f6f7877ecd19204061077d4ce1e2ce2c3..cbe0c75b7d923176473dc55456345d4fee719b1f 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php @@ -20,7 +20,7 @@ class Header extends Block * * @var string */ - protected $adminAccountLink = '.admin-user-account'; + protected $adminAccountLink = '.admin-user-account-text'; /** * Selector for Log Out Link. diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Config/PageActions.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Config/PageActions.php index 8ed2b6a7bfb7acdadf0b2fd106939052fb7de5d2..2dbbdd6fe04c8e4a7b57f1fc71316dd4e1c85023 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Config/PageActions.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Config/PageActions.php @@ -23,7 +23,7 @@ class PageActions extends AbstractPageActions * * @var string */ - protected $scopeSelector = '.actions.dropdown'; + protected $scopeSelector = '.store-switcher .actions.dropdown'; /** * Select store @@ -41,7 +41,7 @@ class PageActions extends AbstractPageActions } /** - * Check if store visible in scope dropdown + * Check if store is visible in scope dropdown * * @param Store $store * @return bool diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php index 59a11f436051b6e190f286e7c9f1feb12fa2e50b..40d04bc0fd76f92725a84952a1c143dc8fee50b9 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php @@ -32,7 +32,7 @@ abstract class Grid extends Block * * @var string */ - protected $searchButton = '[title=Search][class*=action]'; + protected $searchButton = '[data-action="grid-filter-apply"]'; /** * Locator for 'Sort' link @@ -46,7 +46,7 @@ abstract class Grid extends Block * * @var string */ - protected $resetButton = '.action-reset'; + protected $resetButton = '[data-action="grid-filter-reset"]'; /** * The first row in grid. For this moment we suggest that we should strictly define what we are going to search @@ -137,21 +137,14 @@ abstract class Grid extends Block * * @var string */ - protected $filterButton = '.action.filters-toggle'; + protected $filterButton = '[data-action="grid-filter-expand"]'; /** * Active class * * @var string */ - protected $active = '.active'; - - /** - * Base part of row locator template for getRow() method - * - * @var string - */ - protected $location = '//div[@class="grid"]//tr['; + protected $active = '[class=*_active]'; /** * Secondary part of row locator template for getRow() method @@ -381,16 +374,12 @@ abstract class Grid extends Block if ($isSearchable) { $this->search($filter); } - $location = '//div[@class="grid"]//tr['; - $rowTemplate = 'td[contains(.,normalize-space("%s"))]'; - if ($isStrict) { - $rowTemplate = 'td[text()[normalize-space()="%s"]]'; - } + $rowTemplate = ($isStrict) ? $this->rowTemplateStrict : $this->rowTemplate; $rows = []; foreach ($filter as $value) { $rows[] = sprintf($rowTemplate, $value); } - $location = $location . implode(' and ', $rows) . ']'; + $location = '//tr[' . implode(' and ', $rows) . ']'; return $this->_rootElement->find($location, Locator::SELECTOR_XPATH); } @@ -428,7 +417,6 @@ abstract class Grid extends Block */ public function isRowVisible(array $filter, $isSearchable = true, $isStrict = true) { - $this->openFilterBlock(); return $this->getRow($filter, $isSearchable, $isStrict)->isVisible(); } @@ -457,14 +445,14 @@ abstract class Grid extends Block { $this->getTemplateBlock()->waitForElementNotVisible($this->loader); - $button = $this->_rootElement->find($this->filterButton); - if ($button->isVisible() && !$this->_rootElement->find($this->filterButton . $this->active)->isVisible()) { - $button->click(); + $toggleFilterButton = $this->_rootElement->find($this->filterButton); + $searchButton = $this->_rootElement->find($this->searchButton); + if ($toggleFilterButton->isVisible() && !$searchButton->isVisible()) { + $toggleFilterButton->click(); $browser = $this->_rootElement; - $selector = $this->searchButton; $browser->waitUntil( - function () use ($browser, $selector) { - return $browser->find($selector)->isVisible() ? true : null; + function () use ($searchButton) { + return $searchButton->isVisible() ? true : null; } ); } diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/AdminAuthLogin.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/AdminAuthLogin.php index 19ee690cba1cf208e20885459ea8fd11e32ffbf6..b262b81e09c0ebfdcef2d6ff555e9d756713aa8e 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/AdminAuthLogin.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/AdminAuthLogin.php @@ -38,7 +38,7 @@ class AdminAuthLogin extends Page * * @var string */ - protected $messagesBlock = '.messages .message'; + protected $messagesBlock = '.messages'; /** * Constructor. diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php index 535cc6ef859eaa1d2a01df74a95d2625b8025b21..c4a1925081da60591b258109dcc11ed13326b030 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php @@ -23,6 +23,13 @@ class ListProduct extends Block */ protected $productItem = './/*[contains(@class,"product-item-link") and normalize-space(text())="%s"]/ancestor::li'; + /** + * Locator for product item link. + * + * @var string + */ + protected $productItemLink = '.product-item-link'; + /** * Sorter dropdown selector. * @@ -46,6 +53,23 @@ class ListProduct extends Block ); } + /** + * Get product names list. + * + * @return array + */ + public function getProductNames() + { + $itemLinks = $this->_rootElement->getElements($this->productItemLink); + $productNames = []; + + foreach ($itemLinks as $itemLink) { + $productNames[] = trim($itemLink->getText()); + } + + return $productNames; + } + /** * Get all terms used in sort. * diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php index e684946a46f47f152fdd1d4373f31a31b1142dd4..bd7a938684dd27bf7d38724ecc1f6cd046788381 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php @@ -6,6 +6,7 @@ namespace Magento\Catalog\Test\Handler\Category; +use Magento\Catalog\Test\Fixture\Category; use Magento\Mtf\Fixture\FixtureInterface; use Magento\Mtf\Handler\Curl as AbstractCurl; use Magento\Mtf\Util\Protocol\CurlInterface; @@ -58,20 +59,24 @@ class Curl extends AbstractCurl implements CategoryInterface * * @param FixtureInterface|null $fixture [optional] * @return array + * @throws \Exception */ public function persist(FixtureInterface $fixture = null) { $data = $this->prepareData($fixture); - $url = $_ENV['app_backend_url'] . 'catalog/category/save/store/0/parent/' . $data['general']['parent_id'] . '/'; $curl = new BackendDecorator(new CurlTransport(), $this->_configuration); $curl->write(CurlInterface::POST, $url, '1.0', [], $data); $response = $curl->read(); $curl->close(); + if (!strpos($response, 'data-ui-id="messages-message-success"')) { + $this->_eventManager->dispatchEvent(['curl_failed'], [$response]); + throw new \Exception('Category creation by curl handler was not successful!'); + } + preg_match('#http://.+/id/(\d+).+store/#m', $response, $matches); $id = isset($matches[1]) ? (int)$matches[1] : null; - return ['id' => $id]; } @@ -83,12 +88,16 @@ class Curl extends AbstractCurl implements CategoryInterface */ protected function prepareData(FixtureInterface $fixture) { - $data['general'] = $this->replaceMappingData($fixture->getData()); - $data['is_anchor'] = isset($data['is_anchor']) ? $data['is_anchor'] : 0; + $data = ['general' => $this->replaceMappingData($fixture->getData())]; + $data['general']['is_anchor'] = isset($data['general']['is_anchor']) ? $data['general']['is_anchor'] : 0; + if ($fixture->hasData('landing_page')) { $data['general']['landing_page'] = $this->getBlockId($fixture->getLandingPage()); } + $data['category_products'] = $this->prepareCategoryProducts($fixture); + unset($data['general']['category_products']); + $diff = array_diff($this->dataUseConfig, array_keys($data['general'])); if (!empty($diff)) { $data['use_config'] = $diff; @@ -97,6 +106,28 @@ class Curl extends AbstractCurl implements CategoryInterface return $data; } + /** + * Prepare category products data for curl. + * + * @param FixtureInterface $category + * @return array + */ + protected function prepareCategoryProducts(FixtureInterface $category) + { + $categoryProducts = []; + $defaultPosition = 0; + + /** @var Category $category */ + if ($category->hasData('category_products')) { + $products = $category->getDataFieldConfig('category_products')['source']->getProducts(); + foreach ($products as $product) { + $categoryProducts[$product->getId()] = $defaultPosition; + } + } + + return json_encode($categoryProducts); + } + /** * Getting block id by name. * diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml index 392a1ff131e7fbee4246d32285458c1c4d086030..45839712e35c673123d36d46d33b1aaa8b869979 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> <page name="CatalogCategoryView" area="Category" mca="catalog/category/view" module="Magento_Catalog"> <block name="titleBlock" class="Magento\Theme\Test\Block\Html\Title" locator=".page-title-wrapper h1.page-title .base" strategy="css selector"/> - <block name="layeredNavigationBlock" class="Magento\LayeredNavigation\Test\Block\Navigation" locator=".block.filter" strategy="css selector"/> <block name="widgetView" class="Magento\Widget\Test\Block\WidgetView" locator=".widget" strategy="css selector"/> <block name="viewBlock" class="Magento\Catalog\Test\Block\Category\View" locator="#maincontent" strategy="css selector"/> <block name="listProductBlock" class="Magento\Catalog\Test\Block\Product\ListProduct" locator=".products.wrapper.grid" strategy="css selector"/> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml index 4998c9d9604744c84511a07a10c321a6cc29bd02..c4ae2d72fde4dc62c6c352172b7510b3a237138e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml @@ -65,6 +65,31 @@ </field> </dataset> + <dataset name="product_20_dollar"> + <field name="attribute_set_id" xsi:type="array"> + <item name="dataSet" xsi:type="string">default</item> + </field> + <field name="name" xsi:type="string">product_20_dollar %isolation%</field> + <field name="sku" xsi:type="string">sku_product_20_dollar_%isolation%</field> + <field name="is_virtual" xsi:type="string">No</field> + <field name="weight" xsi:type="string">1</field> + <field name="quantity_and_stock_status" xsi:type="array"> + <item name="qty" xsi:type="string">1000</item> + <item name="is_in_stock" xsi:type="string">In Stock</item> + </field> + <field name="price" xsi:type="array"> + <item name="value" xsi:type="string">20</item> + </field> + <field name="tax_class_id" xsi:type="array"> + <item name="dataSet" xsi:type="string">taxable_goods</item> + </field> + <field name="website_ids" xsi:type="array"> + <item name="0" xsi:type="string">Main Website</item> + </field> + <field name="visibility" xsi:type="string">Catalog, Search</field> + <field name="url_key" xsi:type="string">product-20-dollar-%isolation%</field> + </dataset> + <dataset name="product_with_url_key"> <field name="name" xsi:type="string">Simple Product %isolation%</field> <field name="sku" xsi:type="string">sku_simple_product_%isolation%</field> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index b4b2da10a3d7350c0a210b8c9d4bdf3b67c8ec64..83d80113af0ae3d885bd6e2f706b904a39164dfd 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -69,7 +69,6 @@ <data name="category/data/available_product_listing_config" xsi:type="string">Yes</data> <data name="category/data/default_product_listing_config" xsi:type="string">Yes</data> <data name="category/data/use_config_price_range" xsi:type="string">Yes</data> - <data name="category/data/category_products_data/preset" xsi:type="string">default</data> <data name="category/data/category_products/dataSet" xsi:type="string">catalogProductSimple::default,catalogProductSimple::default</data> <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> @@ -97,7 +96,6 @@ <data name="category/data/default_sort_by" xsi:type="string">Price</data> <data name="category/data/use_config_price_range" xsi:type="string">No</data> <data name="category/data/layered_navigation_price_step" xsi:type="string">50</data> - <data name="category/data/category_products_data/preset" xsi:type="string">default</data> <data name="category/data/category_products/dataSet" xsi:type="string">catalogProductSimple::default,catalogProductSimple::default</data> <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/AbstractCatalogRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/AbstractCatalogRuleEntityTest.php index 8c2ab9474a2c002767159584ba680781934ade83..8cc2bbcd11900b03ac123fee638555e84de93a19 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/AbstractCatalogRuleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/AbstractCatalogRuleEntityTest.php @@ -38,13 +38,6 @@ abstract class AbstractCatalogRuleEntityTest extends Injectable */ protected $adminCache; - /** - * Fixture CatalogRule. - * - * @var array - */ - protected $catalogRules = []; - /** * Fixture factory. * @@ -80,12 +73,6 @@ abstract class AbstractCatalogRuleEntityTest extends Injectable */ public function tearDown() { - foreach ($this->catalogRules as $catalogRule) { - $filter = ['name' => $catalogRule->getName()]; - $this->catalogRuleIndex->open(); - $this->catalogRuleIndex->getCatalogRuleGrid()->searchAndOpen($filter); - $this->catalogRuleNew->getFormPageActions()->delete(); - } - $this->catalogRules = []; + $this->objectManager->create('\Magento\CatalogRule\Test\TestStep\DeleteAllCatalogRulesStep')->run(); } } diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplySeveralCatalogPriceRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplySeveralCatalogPriceRuleEntityTest.php index 84f9cd923b6ef87fa44b77d82c0874529f0362fa..1ef4e30a3e542de934a5f0b55e214460b385c8a5 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplySeveralCatalogPriceRuleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplySeveralCatalogPriceRuleEntityTest.php @@ -9,17 +9,15 @@ namespace Magento\CatalogRule\Test\TestCase; use Magento\Catalog\Test\Fixture\CatalogProductSimple; /** - * Test Creation for Apply several CatalogPriceRuleEntity - * - * Test Flow: * Preconditions: - * 1. Execute before each variation: - * - Delete all active catalog price rules - * - Create catalog price rule from dataSet using Curl + * 1. Execute before each variation: + * - Delete all active catalog price rules + * - Create catalog price rule from dataSet using Curl + * * Steps: - * 1. Apply all created rules - * 2. Create simple product - * 3. Perform all assertions + * 1. Apply all created rules. + * 2. Create simple product. + * 3. Perform all assertions. * * @group Catalog_Price_Rules_(MX) * @ZephyrId MAGETWO-24780 @@ -32,7 +30,7 @@ class ApplySeveralCatalogPriceRuleEntityTest extends AbstractCatalogRuleEntityTe /* end tags */ /** - * Apply several catalog price rules + * Apply several catalog price rules. * * @param array $catalogRulesOriginal * @return array @@ -44,15 +42,15 @@ class ApplySeveralCatalogPriceRuleEntityTest extends AbstractCatalogRuleEntityTe if ($catalogPriceRule == '-') { continue; } - $this->catalogRules[$key] = $this->fixtureFactory->createByCode( + $catalogRules[$key] = $this->fixtureFactory->createByCode( 'catalogRule', ['dataSet' => $catalogPriceRule] ); - $this->catalogRules[$key]->persist(); + $catalogRules[$key]->persist(); $filter = [ - 'name' => $this->catalogRules[$key]->getName(), - 'rule_id' => $this->catalogRules[$key]->getId(), + 'name' => $catalogRules[$key]->getName(), + 'rule_id' => $catalogRules[$key]->getId(), ]; $this->catalogRuleIndex->getCatalogRuleGrid()->searchAndOpen($filter); $this->catalogRuleNew->getFormPageActions()->saveAndApply(); diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.php index 20ddb3397e1a54e507e8dd9893b587a79caea588..be62cb21448e54bfb45f6d86c18f3019b485a66a 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogPriceRuleEntityTest.php @@ -9,15 +9,13 @@ namespace Magento\CatalogRule\Test\TestCase; use Magento\CatalogRule\Test\Fixture\CatalogRule; /** - * Test Creation for Create CatalogPriceRuleEntity - * - * Test Flow: + * Steps: * 1. Log in as default admin user. - * 2. Go to Marketing > Catalog Price Rules - * 3. Press "+" button to start create new catalog price rule - * 4. Fill in all data according to data set - * 5. Save rule - * 6. Perform appropriate assertions + * 2. Go to Marketing > Catalog Price Rules. + * 3. Press "+" button to start create new catalog price rule. + * 4. Fill in all data according to data set. + * 5. Save rule. + * 6. Perform appropriate assertions. * * @group Catalog_Price_Rules_(MX) * @ZephyrId MAGETWO-24341 @@ -42,8 +40,5 @@ class CreateCatalogPriceRuleEntityTest extends AbstractCatalogRuleEntityTest $this->catalogRuleIndex->getGridPageActions()->addNew(); $this->catalogRuleNew->getEditForm()->fill($catalogPriceRule); $this->catalogRuleNew->getFormPageActions()->save(); - - // Prepare data for tear down - $this->catalogRules[] = $catalogPriceRule; } } diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php index 6649d45ba0e6312653b5c6766ab1727f20786aed..18815f160fa7f9f1b2ea52a6b64a8b28ad32c568 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php @@ -12,18 +12,16 @@ use Magento\Catalog\Test\Fixture\CatalogProductSimple; use Magento\Customer\Test\Fixture\CustomerGroupInjectable; /** - * Test Coverage for Create Catalog Rule - * - * Test Flow: + * Steps: * 1. Log in as default admin user. - * 2. Go to Marketing > Catalog Price Rules - * 3. Press "+" button to start create new catalog price rule - * 4. Fill in all data according to data set - * 5. Save rule - * 6. Apply newly created catalog rule - * 7. Create simple product - * 8. Clear cache - * 9. Perform all assertions + * 2. Go to Marketing > Catalog Price Rules. + * 3. Press "+" button to start create new catalog price rule. + * 4. Fill in all data according to data set. + * 5. Save rule. + * 6. Apply newly created catalog rule. + * 7. Create simple product. + * 8. Clear cache. + * 9. Perform all assertions. * * @ticketId MAGETWO-23036 */ @@ -37,7 +35,7 @@ class CreateCatalogRuleTest extends AbstractCatalogRuleEntityTest /* end tags */ /** - * Create Catalog Price Rule + * Create Catalog Price Rule. * * @param CatalogRule $catalogPriceRule * @param Customer $customer @@ -70,9 +68,6 @@ class CreateCatalogRuleTest extends AbstractCatalogRuleEntityTest $this->catalogRuleNew->getEditForm()->fill($catalogPriceRule, null, $replace); $this->catalogRuleNew->getFormPageActions()->save(); - // Prepare data for tear down - $this->catalogRules[] = $catalogPriceRule; - // Apply Catalog Price Rule $this->catalogRuleIndex->getGridPageActions()->applyRules(); diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.php index 29339f794b99555a85bd92961ac02a638902d344..fd30614dd24abfbdd239882132548305f5199cd0 100755 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.php @@ -11,19 +11,17 @@ use Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds; use Magento\CatalogRule\Test\Fixture\CatalogRule; /** - * Test Creation for UpdateCatalogPriceRuleEntity - * - * Test Flow: * Preconditions: - * 1. Catalog Price Rule is created + * 1. Catalog Price Rule is created. + * * Steps: - * 1. Login to backend - * 2. Navigate to MARKETING > Catalog Price Rules - * 3. Click Catalog Price Rule from grid - * 4. Edit test value(s) according to dataSet - * 5. Click 'Save'/ 'Apply' button - * 6. Create simple product with category - * 7. Perform all asserts + * 1. Login to backend. + * 2. Navigate to MARKETING > Catalog Price Rules. + * 3. Click Catalog Price Rule from grid. + * 4. Edit test value(s) according to dataSet. + * 5. Click 'Save'/ 'Apply' button. + * 6. Create simple product with category. + * 7. Perform all asserts. * * @group Catalog_Price_Rules_(MX) * @ZephyrId MAGETWO-25187 @@ -37,7 +35,7 @@ class UpdateCatalogPriceRuleEntityTest extends AbstractCatalogRuleEntityTest /* end tags */ /** - * Update catalog price rule + * Update catalog price rule. * * @param CatalogRule $catalogPriceRule * @param CatalogRule $catalogPriceRuleOriginal @@ -81,9 +79,6 @@ class UpdateCatalogPriceRuleEntityTest extends AbstractCatalogRuleEntityTest $this->catalogRuleNew->getEditForm()->fill($catalogPriceRule, null, $replace); $this->catalogRuleNew->getFormPageActions()->$saveAction(); - // Prepare data for tear down - $this->catalogRules[] = $catalogPriceRule; - // Create simple product with category $productSimple->persist(); diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestStep/DeleteAllCatalogRulesStep.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestStep/DeleteAllCatalogRulesStep.php index a30825ebf60af09f0a09ddd652c6d9c7af830cb5..dcc06c224c0baafb2d9429ba256b7d922cbb6136 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestStep/DeleteAllCatalogRulesStep.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestStep/DeleteAllCatalogRulesStep.php @@ -51,6 +51,7 @@ class DeleteAllCatalogRulesStep implements TestStepInterface public function run() { $this->catalogRuleIndex->open(); + $this->catalogRuleIndex->getCatalogRuleGrid()->resetFilter(); while ($this->catalogRuleIndex->getCatalogRuleGrid()->isFirstRowVisible()) { $this->catalogRuleIndex->getCatalogRuleGrid()->openFirstRow(); $this->catalogRuleNew->getFormPageActions()->delete(); diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestStep/DeleteAllTermsEntityStep.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestStep/DeleteAllTermsEntityStep.php index f57baf78acc59aed8fce6d8dfae84cc00ce924ed..3599882b174c192c6f0638b491a86937e7e39c8c 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestStep/DeleteAllTermsEntityStep.php +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestStep/DeleteAllTermsEntityStep.php @@ -52,6 +52,7 @@ class DeleteAllTermsEntityStep implements TestStepInterface public function run() { $this->agreementIndex->open(); + $this->agreementIndex->getAgreementGridBlock()->resetFilter(); while ($this->agreementIndex->getAgreementGridBlock()->isFirstRowVisible()) { $this->agreementIndex->getAgreementGridBlock()->openFirstRow(); $this->agreementNew->getPageActionsBlock()->delete(); diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Block/CmsGrid.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Block/CmsGrid.php index df52dfb3a70cb31a819d4cb0aa9f95248b82536e..99fe29e6517c8fe34fb3a6bc2e4113d5ff161955 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Block/CmsGrid.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Block/CmsGrid.php @@ -20,25 +20,23 @@ class CmsGrid extends Grid */ protected $filters = [ 'title' => [ - 'selector' => '#title', + 'selector' => '[name="params[filters][title]"]', ], 'identifier' => [ - 'selector' => '#identifier', + 'selector' => '[name="params[filters][identifier]"]', ], 'is_active' => [ - 'selector' => '#is_active', + 'selector' => '[name="params[filters][is_active]"]', 'input' => 'select', ], 'creation_time_from' => [ - 'selector' => '(//span[.="Created"]/following::input[contains(@placeholder,"From")])[1]', - 'strategy' => 'xpath', + 'selector' => '[name="params[filters][creation_time][from]"]', ], 'update_time_from' => [ - 'selector' => '(//span[.="Created"]/following::input[contains(@placeholder,"From")])[2]', - 'strategy' => 'xpath', + 'selector' => '[name="params[filters][update_time][from]"]', ], 'store_id' => [ - 'selector' => 'label[for="store_id"] + div > select', + 'selector' => '[name="params[filters][store_id]"]', 'input' => 'selectstore' ], ]; @@ -48,19 +46,19 @@ class CmsGrid extends Grid * * @var string */ - protected $searchButton = '.action-apply'; + protected $searchButton = '[data-action="grid-filter-apply"]'; /** * Locator value for 'Reset' button. * * @var string */ - protected $resetButton = '.action-reset'; + protected $resetButton = '[data-action="grid-filter-reset"]'; /** * Locator value for link in action column. * * @var string */ - protected $editLink = 'td[data-part="body.row.cell"]'; + protected $editLink = '.action-menu-item'; } diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php index b58dfde4c16cb99902cfcb46a600a58cb00436b3..b111912748e06fee7328c8dc50c3e8baea2a0f36 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php @@ -19,21 +19,21 @@ class Grid extends ParentGrid * * @var string */ - protected $searchButton = '.action.primary.action-apply'; + protected $searchButton = '[data-action="grid-filter-apply"]'; /** * Locator value for 'Reset' button. * * @var string */ - protected $resetButton = '.action.secondary.action-reset'; + protected $resetButton = '[data-action="grid-filter-reset"]'; /** * Locator value for link in action column. * * @var string */ - protected $editLink = 'td[data-part="body.row.cell"]'; + protected $editLink = '[data-action="grid-row-edit"]'; /** * 'Preview' cms page link. @@ -49,7 +49,7 @@ class Grid extends ParentGrid */ protected $filters = [ 'title' => [ - 'selector' => '#title', + 'selector' => '[name="params[filters][title]"]', ], ]; diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsBlockIndex.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsBlockIndex.xml index b62397be96d8a79f01c43bb426b4d8c9a521e79b..7f0434e5c657330fc233047676a40e399944d953 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsBlockIndex.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsBlockIndex.xml @@ -6,9 +6,9 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> - <page name="CmsBlockIndex" area="Adminhtml" mca="cms/block" module="Magento_Cms"> - <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector" /> + <page name="CmsBlockIndex" area="Adminhtml" mca="cms/block/index" module="Magento_Cms"> + <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".messages .message" strategy="css selector" /> <block name="gridPageActions" class="Magento\Backend\Test\Block\GridPageActions" locator=".page-main-actions" strategy="css selector" /> - <block name="cmsBlockGrid" class="Magento\Cms\Test\Block\Adminhtml\Block\CmsGrid" locator=".grid" strategy="css selector" /> + <block name="cmsBlockGrid" class="Magento\Cms\Test\Block\Adminhtml\Block\CmsGrid" locator=".admin__data-grid-wrap" strategy="css selector" /> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsPageIndex.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsPageIndex.xml index 6c567cc3013ddba21ed268b8e4f537502a69fa06..44247cb0b215791070dcc32cf16d3d632a3c00b2 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsPageIndex.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/Adminhtml/CmsPageIndex.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> <page name="CmsPageIndex" area="Adminhtml" mca="cms/page/index" module="Magento_Cms"> <block name="pageActionsBlock" class="Magento\Backend\Test\Block\GridPageActions" locator=".page-main-actions" strategy="css selector" /> - <block name="cmsPageGridBlock" class="Magento\Cms\Test\Block\Adminhtml\Page\Grid" locator=".grid" strategy="css selector" /> + <block name="cmsPageGridBlock" class="Magento\Cms\Test\Block\Adminhtml\Page\Grid" locator=".admin__data-grid-wrap" strategy="css selector" /> <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".messages .message" strategy="css selector" /> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/MainPageActions.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/MainPageActions.php deleted file mode 100644 index 14f7bf7af1bbeb49f34f4d68fe6e2bfa046039cd..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/MainPageActions.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency; - -use Magento\Backend\Test\Block\PageActions; - -/** - * Class MainPageActions - * Main page actions on the SystemCurrencyIndex page - */ -class MainPageActions extends PageActions -{ - /** - * "Save Currency Rates" button locator - * - * @var string - */ - protected $saveCurrentRate = '[data-ui-id="page-actions-toolbar-save-button"]'; - - /** - * Save Currency Rates - * - * @return void - */ - public function saveCurrentRate() - { - $this->_rootElement->find($this->saveCurrentRate)->click(); - } -} diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/CurrencyRateForm.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/CurrencyRateForm.php new file mode 100644 index 0000000000000000000000000000000000000000..d5d1c887a484c6d4c46a641cacb4213f5d4e4a58 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/CurrencyRateForm.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\Rate; + +use Magento\Mtf\Block\Form; +use Magento\Mtf\Fixture\FixtureInterface; +use Magento\Mtf\Client\Element\SimpleElement; + +/** + * Currency Rate form. + */ +class CurrencyRateForm extends Form +{ + /** + * Fill currency rate form. + * + * @param FixtureInterface $fixture + * @param SimpleElement|null $element + * @return $this + */ + public function fill(FixtureInterface $fixture, SimpleElement $element = null) + { + /** @var \Magento\Directory\Test\Fixture\CurrencyRate $fixture */ + $this->placeholders['currency_from'] = $fixture->getCurrencyFrom(); + $this->placeholders['currency_to'] = $fixture->getCurrencyTo(); + $this->applyPlaceholders(); + + return parent::fill($fixture, $element); + } +} diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/CurrencyRateForm.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/CurrencyRateForm.xml new file mode 100644 index 0000000000000000000000000000000000000000..4ffc8f05740d4454c14ded3bdc171699a7d93c1c --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/CurrencyRateForm.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<mapping strict="0"> + <wrapper>rate</wrapper> + <fields> + <rate> + <selector>input[name="rate[%currency_from%][%currency_to%]"]</selector> + </rate> + </fields> +</mapping> diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/FormPageActions.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/FormPageActions.php new file mode 100644 index 0000000000000000000000000000000000000000..3c911026ad68cfce9ae4fd9f86caa607863ebe96 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/FormPageActions.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\Rate; + +use Magento\Backend\Test\Block\FormPageActions as ParentFormPageActions; + +/** + * Form page actions on the SystemCurrencyIndex page. + */ +class FormPageActions extends ParentFormPageActions +{ + /** + * "Save Currency Rates" button locator. + * + * @var string + */ + protected $saveButton = '.save'; +} diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/GridPageActions.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/GridPageActions.php similarity index 68% rename from dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/GridPageActions.php rename to dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/GridPageActions.php index f50f9a58386a4aa4ccada29a5115324aad6e4e57..ee7d3fcc6411632c646c08eaec8ab6ee8aa0d904 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/GridPageActions.php +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Block/Adminhtml/System/Currency/Rate/GridPageActions.php @@ -4,10 +4,9 @@ * See COPYING.txt for license details. */ -namespace Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency; +namespace Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\Rate; use Magento\Backend\Test\Block\PageActions; -use Magento\Backend\Test\Block\Messages; /** * Grid page actions on the SystemCurrencyIndex page. @@ -47,21 +46,5 @@ class GridPageActions extends PageActions return $message->isVisible() ? true : null; } ); - if ($this->getMessageBlock()->isVisibleMessage('warning')) { - throw new \Exception($this->getMessageBlock()->getWarningMessages()); - } - } - - /** - * Get message block. - * - * @return Messages - */ - protected function getMessageBlock() - { - return $this->blockFactory->create( - 'Magento\Backend\Test\Block\Messages', - ['element' => $this->_rootElement->find($this->message)] - ); } } diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Page/Adminhtml/SystemCurrencyIndex.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Page/Adminhtml/SystemCurrencyIndex.xml index 2ab90fb8688ebec958d8c4d8f30b9c643370e1db..efcc314043ecb2c455c908f3bc051697e7a85d42 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Page/Adminhtml/SystemCurrencyIndex.xml +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Page/Adminhtml/SystemCurrencyIndex.xml @@ -7,7 +7,9 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> <page name="SystemCurrencyIndex" area="Adminhtml" mca="admin/system_currency/index" module="Magento_CurrencySymbol"> - <block name="gridPageActions" class="Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\GridPageActions" locator=".grid-actions" strategy="css selector"/> - <block name="mainPageActions" class="Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\MainPageActions" locator=".page-main-actions" strategy="css selector"/> + <block name="gridPageActions" class="Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\Rate\GridPageActions" locator=".grid-actions" strategy="css selector"/> + <block name="formPageActions" class="Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\Rate\FormPageActions" locator=".page-main-actions" strategy="css selector"/> + <block name="currencyRateForm" class="Magento\CurrencySymbol\Test\Block\Adminhtml\System\Currency\Rate\CurrencyRateForm" locator="#rate-form" strategy="css selector"/> + <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector"/> </page> -</config> \ No newline at end of file +</config> diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml index 1d7fabcdeb20a6b5c12d4fd33bb4e929bf7066bb..17373832ad976111b47b2f57bbcf04f48f9b54a4 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml @@ -137,5 +137,27 @@ <item name="value" xsi:type="string">USD</item> </field> </dataset> + + <dataset name="config_currency_symbols_usd_and_eur"> + <field name="currency/options/allow" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="array"> + <item name="US Dollar" xsi:type="string">USD</item> + <item name="Euro" xsi:type="string">EUR</item> + </item> + </field> + </dataset> + + <dataset name="config_currency_symbols_usd_and_gbp"> + <field name="currency/options/allow" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="array"> + <item name="US Dollar" xsi:type="string">USD</item> + <item name="British Pound Sterling" xsi:type="string">GBP</item> + </item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/AbstractCurrencySymbolEntityTest.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/AbstractCurrencySymbolEntityTest.php new file mode 100644 index 0000000000000000000000000000000000000000..157b6dae2e1a1be571d2e7cbd7b3adcbbed1981e --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/AbstractCurrencySymbolEntityTest.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CurrencySymbol\Test\TestCase; + +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\TestCase\Injectable; +use Magento\Catalog\Test\Fixture\CatalogProductSimple; +use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencyIndex; +use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencySymbolIndex; + +/** + * Abstract class for currency symbol tests. + */ +abstract class AbstractCurrencySymbolEntityTest extends Injectable +{ + /** + * System Currency Symbol grid page. + * + * @var SystemCurrencySymbolIndex + */ + protected $currencySymbolIndex; + + /** + * System currency index page. + * + * @var SystemCurrencyIndex + */ + protected $currencyIndex; + + /** + * Fixture Factory. + * + * @var FixtureFactory + */ + protected $fixtureFactory; + + /** + * Create simple product and inject pages. + * + * @param SystemCurrencySymbolIndex $currencySymbolIndex + * @param SystemCurrencyIndex $currencyIndex + * @param FixtureFactory $fixtureFactory + * @return array + */ + public function __inject( + SystemCurrencySymbolIndex $currencySymbolIndex, + SystemCurrencyIndex $currencyIndex, + FixtureFactory $fixtureFactory + ) { + $this->currencySymbolIndex = $currencySymbolIndex; + $this->currencyIndex = $currencyIndex; + $this->fixtureFactory = $fixtureFactory; + $product = $this->fixtureFactory->createByCode( + 'catalogProductSimple', + ['dataSet' => 'product_with_category'] + ); + $product->persist(); + + return ['product' => $product]; + } + + /** + * Import currency rates. + * + * @param string $configData + * @return void + * @throws \Exception + */ + protected function importCurrencyRate($configData) + { + $this->objectManager->getInstance()->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => $configData] + )->run(); + + // Import Exchange Rates for currencies + $this->currencyIndex->open(); + $this->currencyIndex->getGridPageActions()->clickImportButton(); + if ($this->currencyIndex->getMessagesBlock()->isVisibleMessage('warning')) { + throw new \Exception($this->currencyIndex->getMessagesBlock()->getWarningMessages()); + } + $this->currencyIndex->getFormPageActions()->save(); + } + + /** + * Disabling currency which has been added. + * + * @return void + */ + public function tearDown() + { + $this->objectManager->getInstance()->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => 'config_currency_symbols_usd'] + )->run(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/EditCurrencySymbolEntityTest.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/EditCurrencySymbolEntityTest.php index 5d2cc6badaa78bc22e0cec669393579f8e72e42f..c1597a1fbc4e6be9be827097c659276072d8c6ab 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/EditCurrencySymbolEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/EditCurrencySymbolEntityTest.php @@ -6,12 +6,8 @@ namespace Magento\CurrencySymbol\Test\TestCase; -use Magento\Mtf\TestCase\Injectable; -use Magento\Mtf\Fixture\FixtureFactory; use Magento\Catalog\Test\Fixture\CatalogProductSimple; use Magento\CurrencySymbol\Test\Fixture\CurrencySymbolEntity; -use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencyIndex; -use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencySymbolIndex; /** * Preconditions: @@ -27,53 +23,13 @@ use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencySymbolIndex; * @group Currency_(PS) * @ZephyrId MAGETWO-26600 */ -class EditCurrencySymbolEntityTest extends Injectable +class EditCurrencySymbolEntityTest extends AbstractCurrencySymbolEntityTest { /* tags */ const MVP = 'no'; const DOMAIN = 'PS'; /* end tags */ - /** - * System Currency Symbol grid page. - * - * @var SystemCurrencySymbolIndex - */ - protected $currencySymbolIndex; - - /** - * System currency index page. - * - * @var SystemCurrencyIndex - */ - protected $currencyIndex; - - /** - * Create simple product and inject pages. - * - * @param SystemCurrencySymbolIndex $currencySymbolIndex - * @param SystemCurrencyIndex $currencyIndex, - * @param FixtureFactory $fixtureFactory - * @return array - */ - public function __inject( - SystemCurrencySymbolIndex $currencySymbolIndex, - SystemCurrencyIndex $currencyIndex, - FixtureFactory $fixtureFactory - ) { - $this->currencySymbolIndex = $currencySymbolIndex; - $this->currencyIndex = $currencyIndex; - - /**@var CatalogProductSimple $catalogProductSimple */ - $product = $fixtureFactory->createByCode( - 'catalogProductSimple', - ['dataSet' => 'product_with_category'] - ); - $product->persist(); - - return ['product' => $product]; - } - /** * Edit Currency Symbol Entity test. * @@ -91,36 +47,4 @@ class EditCurrencySymbolEntityTest extends Injectable $this->currencySymbolIndex->getCurrencySymbolForm()->fill($currencySymbol); $this->currencySymbolIndex->getPageActions()->save(); } - - /** - * Import currency rates. - * - * @param string $configData - * @return void - */ - protected function importCurrencyRate($configData) - { - $this->objectManager->getInstance()->create( - 'Magento\Config\Test\TestStep\SetupConfigurationStep', - ['configData' => $configData] - )->run(); - - // Import Exchange Rates for currencies - $this->currencyIndex->open(); - $this->currencyIndex->getGridPageActions()->clickImportButton(); - $this->currencyIndex->getMainPageActions()->saveCurrentRate(); - } - - /** - * Disabling currency which has been added. - * - * @return void - */ - public function tearDown() - { - $this->objectManager->getInstance()->create( - 'Magento\Config\Test\TestStep\SetupConfigurationStep', - ['configData' => 'config_currency_symbols_usd'] - )->run(); - } } diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/ResetCurrencySymbolEntityTest.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/ResetCurrencySymbolEntityTest.php index f64c407f6aefffb4f76ccf351282c38556b079ca..96537d399ce8770887994dd6a6b7f9268f3e40f4 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/ResetCurrencySymbolEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/TestCase/ResetCurrencySymbolEntityTest.php @@ -6,12 +6,8 @@ namespace Magento\CurrencySymbol\Test\TestCase; -use Magento\Mtf\TestCase\Injectable; -use Magento\Mtf\Fixture\FixtureFactory; use Magento\Catalog\Test\Fixture\CatalogProductSimple; use Magento\CurrencySymbol\Test\Fixture\CurrencySymbolEntity; -use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencyIndex; -use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencySymbolIndex; /** * Preconditions: @@ -28,77 +24,13 @@ use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencySymbolIndex; * @group Currency_(PS) * @ZephyrId MAGETWO-26638 */ -class ResetCurrencySymbolEntityTest extends Injectable +class ResetCurrencySymbolEntityTest extends AbstractCurrencySymbolEntityTest { /* tags */ const MVP = 'no'; const DOMAIN = 'PS'; /* end tags */ - /** - * System currency symbol grid page. - * - * @var SystemCurrencySymbolIndex - */ - protected $currencySymbolIndex; - - /** - * System currency index page. - * - * @var SystemCurrencyIndex - */ - protected $currencyIndex; - - /** - * Currency symbol entity fixture. - * - * @var CurrencySymbolEntity - */ - protected $currencySymbolDefault; - - /** - * Fixture Factory. - * - * @var FixtureFactory - */ - protected $fixtureFactory; - - /** - * Prepare data. Create simple product. - * - * @param FixtureFactory $fixtureFactory - * @return array - */ - public function __prepare(FixtureFactory $fixtureFactory) - { - $this->fixtureFactory = $fixtureFactory; - $product = $this->fixtureFactory->createByCode( - 'catalogProductSimple', - ['dataSet' => 'product_with_category'] - ); - $product->persist(); - - return ['product' => $product]; - } - - /** - * Injection data. - * - * @param SystemCurrencySymbolIndex $currencySymbolIndex - * @param SystemCurrencyIndex $currencyIndex - * @param CurrencySymbolEntity $currencySymbolDefault - * @return array - */ - public function __inject( - SystemCurrencySymbolIndex $currencySymbolIndex, - SystemCurrencyIndex $currencyIndex, - CurrencySymbolEntity $currencySymbolDefault - ) { - $this->currencySymbolIndex = $currencySymbolIndex; - $this->currencyIndex = $currencyIndex; - $this->currencySymbolDefault = $currencySymbolDefault; - } - /** * Reset Currency Symbol Entity test. * @@ -135,36 +67,4 @@ class ResetCurrencySymbolEntityTest extends Injectable ) ]; } - - /** - * Import currency rates. - * - * @param string $configData - * @return void - */ - protected function importCurrencyRate($configData) - { - $this->objectManager->getInstance()->create( - 'Magento\Config\Test\TestStep\SetupConfigurationStep', - ['configData' => $configData] - )->run(); - - // Import Exchange Rates for currencies - $this->currencyIndex->open(); - $this->currencyIndex->getGridPageActions()->clickImportButton(); - $this->currencyIndex->getMainPageActions()->saveCurrentRate(); - } - - /** - * Disabling currency which has been added. - * - * @return void - */ - public function tearDown() - { - $this->objectManager->getInstance()->create( - 'Magento\Config\Test\TestStep\SetupConfigurationStep', - ['configData' => 'config_currency_symbols_usd'] - )->run(); - } } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/CustomerForm.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/CustomerForm.xml index d8722814679701ed50ae1f70c49025d042738519..bc70891ffa44c1c7dc73bdc6469b37fcd113c886 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/CustomerForm.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/CustomerForm.xml @@ -8,9 +8,9 @@ <tabs> <account_information> <class>\Magento\Backend\Test\Block\Widget\Tab</class> - <selector>#tab_account</selector> + <selector>#tab_customer</selector> <strategy>css selector</strategy> - <wrapper>account</wrapper> + <wrapper>data[customer]</wrapper> <fields> <website_id> <input>select</input> @@ -28,7 +28,7 @@ </account_information> <addresses> <class>\Magento\Customer\Test\Block\Adminhtml\Edit\Tab\Addresses</class> - <selector>#tab_customer_address</selector> + <selector>#tab_address</selector> <strategy>css selector</strategy> </addresses> </tabs> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/Tab/Addresses.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/Tab/Addresses.xml index efef4933c1b7421defaf380157ce9b53cf53e66e..b50ddc0ff54a605085e89611fd4e168a93fe35be 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/Tab/Addresses.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/Edit/Tab/Addresses.xml @@ -70,11 +70,11 @@ <strategy>css selector</strategy> </vat_id> <default_billing> - <selector>#address_list [aria-selected="true"] [name^="account"][name$="[default_billing]"]</selector> + <selector>.ui-state-active [name$="[default_billing]"]</selector> <input>checkbox</input> </default_billing> <default_shipping> - <selector>#address_list [aria-selected="true"] [name^="account"][name$="[default_shipping]"]</selector> + <selector>.ui-state-active [name$="[default_shipping]"]</selector> <input>checkbox</input> </default_shipping> </fields> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php index 67d98b313afe2c576d620daed3c0dfd392d40315..fb1030c3143f16e5496bd47354f74826ed2c457c 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php @@ -34,6 +34,10 @@ class Curl extends AbstractCurl implements CustomerInterface 'United States' => 'US', 'United Kingdom' => 'GB' ], + 'gender' => [ + 'Male' => 1, + 'Female' => 2, + ], 'region_id' => [ 'California' => 12, 'New York' => 43, @@ -47,14 +51,15 @@ class Curl extends AbstractCurl implements CustomerInterface * @var array */ protected $curlMapping = [ - 'account' => [ + 'customer' => [ 'group_id', 'firstname', 'lastname', 'email', 'dob', 'taxvat', - 'gender' + 'gender', + 'entity_id', ] ]; @@ -77,12 +82,11 @@ class Curl extends AbstractCurl implements CustomerInterface */ public function persist(FixtureInterface $customer = null) { - $address = []; - $result = []; /** @var Customer $customer */ - $url = $_ENV['app_frontend_url'] . 'customer/account/createpost/?nocookie=true'; $data = $customer->getData(); $data['group_id'] = $this->getCustomerGroup($customer); + $address = []; + $url = $_ENV['app_frontend_url'] . 'customer/account/createpost/?nocookie=true'; if ($customer->hasData('address')) { $address = $customer->getAddress(); @@ -98,15 +102,14 @@ class Curl extends AbstractCurl implements CustomerInterface throw new \Exception("Customer entity creating by curl handler was not successful! Response: $response"); } - $result['id'] = $this->getCustomerId($customer->getEmail()); - $data['customer_id'] = $result['id']; + $data['entity_id'] = $this->getCustomerId($customer->getEmail()); if (!empty($address)) { $data['address'] = $address; } $this->updateCustomer($data); - return $result; + return ['id' => $data['entity_id']]; } /** @@ -167,19 +170,19 @@ class Curl extends AbstractCurl implements CustomerInterface } unset($data['password'], $data['password_confirmation']); - $curlData = $this->replaceMappingData(array_merge($curlData, $data)); + $curlData = $this->replaceMappingData(array_replace_recursive($curlData, $data)); if (!empty($data['address'])) { $curlData = $this->prepareAddressData($curlData); } - $url = $_ENV['app_backend_url'] . 'customer/index/save/id/' . $data['customer_id']; + $url = $_ENV['app_backend_url'] . 'customer/index/save/id/' . $curlData['customer']['entity_id']; $curl = new BackendDecorator(new CurlTransport(), $this->_configuration); $curl->write(CurlInterface::POST, $url, '1.0', [], $curlData); $response = $curl->read(); $curl->close(); if (!strpos($response, 'data-ui-id="messages-message-success"')) { - $this->_eventManager->dispatchEvent(['curl_failed', [$response]]); + $this->_eventManager->dispatchEvent(['curl_failed'], [$response]); throw new \Exception('Failed to update customer!'); } } @@ -200,7 +203,6 @@ class Curl extends AbstractCurl implements CustomerInterface $curlData['address'][$key]['street'] = []; $curlData['address'][$key]['street'][] = $street; } - $newKey = 'new_' . ($key); if (isset($curlData['address'][$key]['default_billing'])) { $value = $curlData['address'][$key]['default_billing'] === 'Yes' ? 'true' : 'false'; $curlData['address'][$key]['default_billing'] = $value; @@ -209,9 +211,7 @@ class Curl extends AbstractCurl implements CustomerInterface $value = $curlData['address'][$key]['default_shipping'] === 'Yes' ? 'true' : 'false'; $curlData['address'][$key]['default_shipping'] = $value; } - $curlData['account']['customer_address'][$newKey] = $curlData['address'][$key]; } - unset($curlData['address']); return $curlData; } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountCreate.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountCreate.xml index 783fa1ad4e1b476da685d85db7e08281163d7256..57cf9a355142c53bce686233fd8ccbf588296f45 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountCreate.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountCreate.xml @@ -6,8 +6,8 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/pages.xsd"> - <page name="CustomerAccountCreate" mca="customer/account/create" module="Magento_Customer"> - <block name="registerForm" class="Magento\Customer\Test\Block\Form\Register" locator="#form-validate" strategy="css selector"/> - <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".page.messages" strategy="css selector"/> - </page> + <page name="CustomerAccountCreate" mca="customer/account/create" module="Magento_Customer"> + <block name="registerForm" class="Magento\Customer\Test\Block\Form\Register" locator="#form-validate[novalidate='novalidate']" strategy="css selector" /> + <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".page.messages" strategy="css selector" /> + </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnCatalogPage.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnCatalogPage.php new file mode 100644 index 0000000000000000000000000000000000000000..05cd0245e1a759d6162a5dca748479844cb551c8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateAppliedOnCatalogPage.php @@ -0,0 +1,71 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Directory\Test\Constraint; + +use Magento\Cms\Test\Page\CmsIndex; +use Magento\Mtf\Constraint\AbstractConstraint; +use Magento\Catalog\Test\Fixture\CatalogProductSimple; +use Magento\Catalog\Test\Page\Category\CatalogCategoryView; +use Magento\CurrencySymbol\Test\Fixture\CurrencySymbolEntity; + +/** + * Assert currency rate applied on catalog page. + */ +class AssertCurrencyRateAppliedOnCatalogPage extends AbstractConstraint +{ + /** + * Assert currency rate applied on catalog page. + * + * @param CmsIndex $cmsIndex + * @param CatalogCategoryView $catalogCategoryView + * @param CatalogProductSimple $product + * @param CurrencySymbolEntity $currencySymbol + * @param string $basePrice + * @param string $convertedPrice + * @return void + */ + public function processAssert( + CmsIndex $cmsIndex, + CatalogCategoryView $catalogCategoryView, + CatalogProductSimple $product, + CurrencySymbolEntity $currencySymbol, + $basePrice, + $convertedPrice + ) { + $categoryName = $product->getCategoryIds()[0]; + $cmsIndex->open(); + $cmsIndex->getTopmenu()->selectCategoryByName($categoryName); + $priceBlock = $catalogCategoryView->getListProductBlock()->getProductItem($product)->getPriceBlock(); + $actualPrice = $priceBlock->getPrice(''); + + \PHPUnit_Framework_Assert::assertEquals( + $basePrice, + $actualPrice, + 'Wrong price is displayed on Category page.' + ); + + $cmsIndex->getCurrencyBlock()->switchCurrency($currencySymbol); + $cmsIndex->getTopmenu()->selectCategoryByName($categoryName); + $actualPrice = $priceBlock->getPrice(''); + + \PHPUnit_Framework_Assert::assertEquals( + $convertedPrice, + $actualPrice, + 'Wrong price is displayed on Category page.' + ); + } + + /** + * Returns a string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return "Currency rate has been applied correctly on Catalog page."; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateSuccessSaveMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..3a9f7e82a3943e73ece72d72fbefb3bc2e720ca5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateSuccessSaveMessage.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Directory\Test\Constraint; + +use Magento\Mtf\Constraint\AbstractConstraint; +use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencyIndex; + +/** + * Assert that success message is displayed. + */ +class AssertCurrencyRateSuccessSaveMessage extends AbstractConstraint +{ + const SUCCESS_MESSAGE = 'All valid rates have been saved.'; + + /** + * Assert that success message is displayed after currency rate saved. + * + * @param SystemCurrencyIndex $currencyIndexPage + * @return void + */ + public function processAssert(SystemCurrencyIndex $currencyIndexPage) + { + $actualMessage = $currencyIndexPage->getMessagesBlock()->getSuccessMessages(); + \PHPUnit_Framework_Assert::assertEquals( + self::SUCCESS_MESSAGE, + $actualMessage, + 'Wrong success message is displayed.' + . "\nExpected: " . self::SUCCESS_MESSAGE + . "\nActual: " . $actualMessage + ); + } + + /** + * Returns a string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return 'Currency rate success create message is present.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Fixture/CurrencyRate.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/Fixture/CurrencyRate.xml new file mode 100644 index 0000000000000000000000000000000000000000..70fcf15c962980ade05464ff3e6a8cebb9b66c85 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Fixture/CurrencyRate.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd"> + <fixture name="currencyRate" module="Magento_Directory" type="flat" entity_type="directory_currency_rate" collection="Magento\Directory\Model\Resource\Currency" identifier="" repository_class="Magento\Directory\Test\Repository\CurrencyRate" handler_interface="Magento\Directory\Test\Handler\CurrencyRate\CurrencyRateInterface" class="Magento\Directory\Test\Fixture\CurrencyRate"> + <dataset name="default"> + <field name="currency_from" xsi:type="string">USD</field> + <field name="currency_to" xsi:type="string">EUR</field> + <field name="rate" xsi:type="number">0.8</field> + </dataset> + + <field name="currency_from" is_required="1" /> + <field name="currency_to" is_required="1" /> + <field name="rate" is_required="1" /> + </fixture> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Handler/CurrencyRate/Curl.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Handler/CurrencyRate/Curl.php new file mode 100644 index 0000000000000000000000000000000000000000..cc6fbf9895588b3ae58c5dd75779c97e54c6a7ce --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Handler/CurrencyRate/Curl.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Directory\Test\Handler\CurrencyRate; + +use Magento\Mtf\Fixture\FixtureInterface; +use Magento\Mtf\Handler\Curl as AbstractCurl; +use Magento\Mtf\Util\Protocol\CurlInterface; +use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator; + +/** + * Curl handler for setting currency rates. + */ +class Curl extends AbstractCurl implements CurrencyRateInterface +{ + /** + * Post request for setting currency rate. + * + * @param FixtureInterface $fixture [optional] + * @return mixed|string + * @throws \Exception + */ + public function persist(FixtureInterface $fixture = null) + { + $data = $this->prepareData($fixture); + + $url = $_ENV['app_backend_url'] . 'admin/system_currency/saveRates/'; + $curl = new BackendDecorator(new CurlTransport(), $this->_configuration); + $curl->write(CurlInterface::POST, $url, '1.0', [], $data); + $response = $curl->read(); + $curl->close(); + + if (!strpos($response, 'data-ui-id="messages-message-success"')) { + throw new \Exception("Currency rates setting by curl handler was not successful! Response:\n" . $response); + } + } + + /** + * Prepare data for POST request. + * + * @param FixtureInterface $fixture + * @return array + */ + protected function prepareData(FixtureInterface $fixture) + { + $result = []; + $data = $fixture->getData(); + $result['rate'][$data['currency_from']][$data['currency_to']] = $data['rate']; + + return $result; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Handler/CurrencyRate/CurrencyRateInterface.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Handler/CurrencyRate/CurrencyRateInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..99cc0f552b190d49268024a33dfa0501e97f8cc7 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Handler/CurrencyRate/CurrencyRateInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Directory\Test\Handler\CurrencyRate; + +use Magento\Mtf\Handler\HandlerInterface; + +/** + * Interface CurrencyRateInterface + */ +interface CurrencyRateInterface extends HandlerInterface +{ + // +} diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/CurrencyRate.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/CurrencyRate.xml new file mode 100644 index 0000000000000000000000000000000000000000..c1b6dc96e3cbb79862eb959f0325f551cb12acf2 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/CurrencyRate.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> + <repository class="Magento\Directory\Test\Repository\CurrencyRate"> + <dataset name="usd_chf_rate_0_9"> + <field name="currency_from" xsi:type="string">USD</field> + <field name="currency_to" xsi:type="string">CHF</field> + <field name="rate" xsi:type="number">0.9</field> + </dataset> + + <dataset name="usd_gbp_rate_0_6"> + <field name="currency_from" xsi:type="string">USD</field> + <field name="currency_to" xsi:type="string">GBP</field> + <field name="rate" xsi:type="number">0.6</field> + </dataset> + </repository> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..04aa6c4ca73d61e4ef01e61ac9929d9a225d2b59 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Directory\Test\TestCase; + +use Magento\Config\Test\Fixture\ConfigData; +use Magento\Mtf\TestCase\Injectable; +use Magento\Directory\Test\Fixture\CurrencyRate; +use Magento\Catalog\Test\Fixture\CatalogProductSimple; +use Magento\CurrencySymbol\Test\Page\Adminhtml\SystemCurrencyIndex; + +/** + * Preconditions: + * 1. Create Simple product and assign it to the category. + * 2. Configure allowed Currencies Options. + * + * Steps: + * 1. Login to backend. + * 2. Go to Stores > Currency > Currency Rates. + * 3. Fill currency rate according to dataSet. + * 4. Click on 'Save Currency Rates' button. + * 5. Perform assertions. + * + * @group Localization_(PS) + * @ZephyrId MAGETWO-12427, MAGETWO-36824 + */ +class CreateCurrencyRateTest extends Injectable +{ + /* tags */ + const TEST_TYPE = 'acceptance_test'; + const DOMAIN = 'PS'; + /* end tags */ + + /** + * Currency rate index page. + * + * @var SystemCurrencyIndex + */ + protected $currencyIndexPage; + + /** + * Inject data. + * + * @param SystemCurrencyIndex $currencyIndexPage + * @return void + */ + public function __inject(SystemCurrencyIndex $currencyIndexPage) + { + $this->currencyIndexPage = $currencyIndexPage; + } + + /** + * Create currency rate test. + * + * @param CurrencyRate $currencyRate + * @param CatalogProductSimple $product + * @param $config + * @return void + */ + public function test(CurrencyRate $currencyRate, CatalogProductSimple $product, ConfigData $config) + { + // Preconditions: + $product->persist(); + $config->persist(); + + // Steps: + $this->currencyIndexPage->open(); + $this->currencyIndexPage->getCurrencyRateForm()->fill($currencyRate); + $this->currencyIndexPage->getFormPageActions()->save(); + } + + /** + * Reset currency config to default values. + * + * @return void + */ + public function tearDown() + { + $this->objectManager->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => 'config_currency_symbols_usd'] + )->run(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..561f9307ff07f058b79e7873e4e7ed15ceb67632 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Directory\Test\TestCase\CreateCurrencyRateTest"> + <variation name="CreateCurrencyRateTestVariation1"> + <data name="currencyRate/data/currency_from" xsi:type="string">USD</data> + <data name="currencyRate/data/currency_to" xsi:type="string">EUR</data> + <data name="currencyRate/data/rate" xsi:type="number">0.8</data> + <data name="currencySymbol/dataSet" xsi:type="string">currency_symbols_eur</data> + <data name="product/dataSet" xsi:type="string">simple_10_dollar</data> + <data name="config/dataSet" xsi:type="string">config_currency_symbols_usd_and_eur</data> + <data name="basePrice" xsi:type="string">$10.00</data> + <data name="convertedPrice" xsi:type="string">€8.00</data> + <data name="tag" xsi:type="string">test_type:acceptance_test</data> + <constraint name="Magento\Directory\Test\Constraint\AssertCurrencyRateSuccessSaveMessage"/> + <constraint name="Magento\Directory\Test\Constraint\AssertCurrencyRateAppliedOnCatalogPage"/> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/etc/curl/di.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/etc/curl/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..0962d9ed807d9206fb6e31b641e4fa133588097c --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/etc/curl/di.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> + <preference for="\Magento\Directory\Test\Handler\CurrencyRate\CurrencyRateInterface" type="\Magento\Directory\Test\Handler\CurrencyRate\Curl" /> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/LinkRow.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/LinkRow.php index 64d1aab3f990b7d1a043a6cce9bd2bc7bd890403..774f85d7772f4f9fdd76ca895448e8045d0a2c1c 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/LinkRow.php +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/LinkRow.php @@ -3,6 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Downloadable\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Downloadable; use Magento\Mtf\Block\Form; @@ -19,7 +20,7 @@ class LinkRow extends Form * * @var string */ - protected $deleteButton = '.action-remove'; + protected $deleteButton = '.action-delete'; /** * Fill item link diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Adminhtml/Order/Create/Items/ItemProduct.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Adminhtml/Order/Create/Items/ItemProduct.php index 3627d161b35ab583e5f5c7ab4a1c919d473c2c6c..77d38c0eb97743553753d2f5d1ae8ba9aa75bbeb 100644 --- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Adminhtml/Order/Create/Items/ItemProduct.php +++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Block/Adminhtml/Order/Create/Items/ItemProduct.php @@ -29,11 +29,11 @@ class ItemProduct extends \Magento\Sales\Test\Block\Adminhtml\Order\Create\Items protected $giftMessageForm = './/*[@role="dialog"][*[@id="gift_options_configure"]]'; /** - * Magento varienLoader.js loader. + * Magento loader. * * @var string */ - protected $loadingMask = '//*[@id="loading-mask"]/*[@id="loading_mask_loader"]'; + protected $loader = '[data-role="loader"]'; /** * Fill GiftMessage form. @@ -58,10 +58,11 @@ class ItemProduct extends \Magento\Sales\Test\Block\Adminhtml\Order\Create\Items ['element' => $this->browser->find($this->giftMessageForm, Locator::SELECTOR_XPATH)] ); $giftMessageForm->fill($giftMessage); - $loadingMask = $this->browser->find($this->loadingMask, Locator::SELECTOR_XPATH); + $loader = $this->loader; $this->browser->waitUntil( - function () use ($loadingMask) { - return !$loadingMask->isVisible() ? true : null; + function () use ($browser, $loader) { + $element = $this->browser->find($loader); + return $element->isVisible() == false ? true : null; } ); } diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml index 3ce7af8e5be7e87a8a7173565d2b67e0740afa88..de5469059a9b89883c6210b648f0783b8af43fd8 100644 --- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/testcase.xml @@ -22,15 +22,9 @@ <step name="placeOrder" module="Magento_Checkout" /> </scenario> <scenario name="CreateGiftMessageOnBackendTest" firstStep="setupConfiguration"> - <step name="setupConfiguration" module="Magento_Config" next="createProducts"> - <item name="configData" value="cashondelivery, enable_gift_messages" /> - </step> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> <step name="createProducts" module="Magento_Catalog" next="createCustomer" /> - <step name="createCustomer" module="Magento_Customer" next="openSalesOrders"> - <item name="customer"> - <item name="dataSet" value="johndoe_with_addresses" /> - </item> - </step> + <step name="createCustomer" module="Magento_Customer" next="openSalesOrders" /> <step name="openSalesOrders" module="Magento_Sales" next="createNewOrder" /> <step name="createNewOrder" module="Magento_Sales" next="selectCustomerOrder" /> <step name="selectCustomerOrder" module="Magento_Sales" next="selectStore" /> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct/CheckoutData.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct/CheckoutData.php index 5c45ad254c0b02f4444547e1b95ebba7fedf2727..2871ec912db01ef8020b14699f62d95c6f7299ac 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct/CheckoutData.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct/CheckoutData.php @@ -57,39 +57,6 @@ class CheckoutData extends \Magento\Catalog\Test\Fixture\CatalogProductSimple\Ch ], ], ], - 'three_simple_products_default_qty' => [ - 'options' => [ - [ - 'name' => 'product_key_0', - 'qty' => 17, - ], - [ - 'name' => 'product_key_1', - 'qty' => 36 - ], - [ - 'name' => 'product_key_2', - 'qty' => 20 - ], - ], - 'cartItem' => [ - 'price' => [ - 'product_key_0' => 560, - 'product_key_1' => 40, - 'product_key_2' => 100, - ], - 'qty' => [ - 'product_key_0' => 17, - 'product_key_1' => 36, - 'product_key_2' => 20, - ], - 'subtotal' => [ - 'product_key_0' => 9520.00, - 'product_key_1' => 1440.00, - 'product_key_2' => 2000.00, - ], - ], - ], ]; return isset($presets[$name]) ? $presets[$name] : null; } diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml index fbf4305699a447b37e9a8d1bd756caec8f1f569e..cd0bc02b3df4ccab18c34b1876eef98e775af553 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml @@ -117,34 +117,5 @@ <item name="preset" xsi:type="string">three_simple_products</item> </field> </dataset> - - <dataset name="three_simple_products_default_qty"> - <field name="name" xsi:type="string">Grouped product %isolation%</field> - <field name="sku" xsi:type="string">grouped_product_%isolation%</field> - <field name="category_ids" xsi:type="array"> - <item name="presets" xsi:type="string">default</item> - </field> - <field name="associated" xsi:type="array"> - <item name="preset" xsi:type="string">three_simple_products</item> - </field> - <field name="status" xsi:type="string">Product online</field> - <field name="visibility" xsi:type="string">Catalog, Search</field> - <field name="tax_class_id" xsi:type="array"> - <item name="dataSet" xsi:type="string">taxable_goods</item> - </field> - <field name="url_key" xsi:type="string">test-grouped-product-%isolation%</field> - <field name="quantity_and_stock_status" xsi:type="array"> - <item name="is_in_stock" xsi:type="string">In Stock</item> - </field> - <field name="website_ids" xsi:type="array"> - <item name="0" xsi:type="string">Main Website</item> - </field> - <field name="attribute_set_id" xsi:type="array"> - <item name="dataSet" xsi:type="string">default</item> - </field> - <field name="checkout_data" xsi:type="array"> - <item name="preset" xsi:type="string">three_simple_products_default_qty</item> - </field> - </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Block/Navigation.php b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Block/Navigation.php index 41376ef7a3735d1af8d8dd8531397518f7f5b0a9..4dfa6dd2122c10aa6a7344210cd47d10985551c0 100644 --- a/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Block/Navigation.php +++ b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Block/Navigation.php @@ -3,13 +3,14 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\LayeredNavigation\Test\Block; use Magento\Mtf\Block\Block; use Magento\Mtf\Client\Locator; /** - * Catalog layered navigation view block + * Catalog layered navigation view block. */ class Navigation extends Block { @@ -20,20 +21,6 @@ class Navigation extends Block */ protected $clearAll = '.action.clear'; - /** - * Price range. - * - * @var string - */ - protected $priceRange = "[href$='?price=%s']"; - - /** - * Attribute option. - * - * @var string - */ - protected $attributeOption = "//a[contains(text(), '%s')]"; - /** * Attribute option title selector. * @@ -42,11 +29,11 @@ class Navigation extends Block protected $optionTitle = '.filter-options-title'; /** - * Attribute option content selector. + * Filter link locator. * * @var string */ - protected $optionContent = '.filter-options-content'; + protected $filterLink = './/dt[contains(text(),"%s")]/following-sibling::dd//a'; /** * Click on 'Clear All' link. @@ -58,28 +45,6 @@ class Navigation extends Block $this->_rootElement->find($this->clearAll, locator::SELECTOR_CSS)->click(); } - /** - * Select product price range. - * - * @param string $range - * @return void - */ - public function selectPriceRange($range) - { - $this->_rootElement->find(sprintf($this->priceRange, $range))->click(); - } - - /** - * Select attribute option. - * - * @param string $optionName - * @return void - */ - public function selectAttributeOption($optionName) - { - $this->_rootElement->find(sprintf($this->attributeOption, $optionName), Locator::SELECTOR_XPATH)->click(); - } - /** * Get array of available filters. * @@ -94,4 +59,25 @@ class Navigation extends Block } return $data; } + + /** + * Click filter link. + * + * @param string $filter + * @param string $linkPattern + * @return void + * @throws \Exception + */ + public function clickFilterLink($filter, $linkPattern) + { + $links = $this->_rootElement->getElements(sprintf($this->filterLink, $filter), Locator::SELECTOR_XPATH); + + foreach ($links as $link) { + if (preg_match($linkPattern, trim($link->getText()))) { + $link->click(); + return; + } + } + throw new \Exception("Can't find {$filter} filter link by pattern: {$linkPattern}"); + } } diff --git a/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Constraint/AssertFilterProductList.php b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Constraint/AssertFilterProductList.php new file mode 100644 index 0000000000000000000000000000000000000000..e2b384a26611026f3c353fd7d8f7185ecab99143 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Constraint/AssertFilterProductList.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\LayeredNavigation\Test\Constraint; + +use Magento\Catalog\Test\Fixture\Category; +use Magento\Catalog\Test\Page\Category\CatalogCategoryView; +use Magento\Cms\Test\Page\CmsIndex; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Check whether products can be filtered in the Frontend via layered navigation. + */ +class AssertFilterProductList extends AbstractConstraint +{ + /** + * Available products list. + * + * @var array + */ + protected $products; + + /** + * Assertion that filtered product list via layered navigation are displayed correctly. + * + * @param Category $category + * @param CmsIndex $cmsIndex + * @param CatalogCategoryView $catalogCategoryView + * @param array $layeredNavigation + * @return void + */ + public function processAssert( + Category $category, + CmsIndex $cmsIndex, + CatalogCategoryView $catalogCategoryView, + array $layeredNavigation + ) { + $this->products = $category->getDataFieldConfig('category_products')['source']->getProducts(); + $cmsIndex->open(); + $cmsIndex->getTopmenu()->selectCategoryByName($category->getName()); + + foreach ($layeredNavigation as $filters) { + foreach ($filters as $filter) { + $catalogCategoryView->getLayeredNavigationBlock()->clickFilterLink( + $filter['title'], + $filter['linkPattern'] + ); + + $productNames = $this->getProductNames($filter['products']); + sort($productNames); + $pageProductNames = $catalogCategoryView->getListProductBlock()->getProductNames(); + sort($pageProductNames); + \PHPUnit_Framework_Assert::assertEquals($productNames, $pageProductNames); + } + $catalogCategoryView->getLayeredNavigationBlock()->clearAll(); + } + } + + /** + * Get product names list by keys. + * + * @param string $productKeys + * @return array + */ + protected function getProductNames($productKeys) + { + $keys = array_map('trim', explode(',', $productKeys)); + $productNames = []; + + foreach ($keys as $key) { + $key = str_replace('product_', '', $key); + $productNames[] = $this->products[$key]->getName(); + } + + return $productNames; + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Filtered product list via layered navigation are displayed correctly.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Page/Category/CatalogCategoryView.xml b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Page/Category/CatalogCategoryView.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3b68e9dd74ccab2655d9d8f307cb4c634e93dfd --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Page/Category/CatalogCategoryView.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> + <page name="CatalogCategoryView" area="Category" mca="catalog/category/view" module="Magento_Catalog"> + <block name="layeredNavigationBlock" class="Magento\LayeredNavigation\Test\Block\Navigation" locator=".block.filter" strategy="css selector"/> + </page> +</config> diff --git a/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Repository/ConfigData.xml new file mode 100644 index 0000000000000000000000000000000000000000..2005dd8bf0cef056edf502e01fd9554e68cb8e23 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/Repository/ConfigData.xml @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> + <repository class="Magento\Config\Test\Repository\ConfigData"> + <dataset name="layered_navigation_manual_range_10"> + <field name="catalog/layered_navigation/display_product_count" xsi:type="array"> + <item name="scope" xsi:type="string">default</item> + <item name="scope_id" xsi:type="number">0</item> + <item name="value" label="Yes" xsi:type="string">1</item> + </field> + <field name="catalog/layered_navigation/price_range_calculation" xsi:type="array"> + <item name="scope" xsi:type="string">default</item> + <item name="scope_id" xsi:type="number">0</item> + <item name="value" label="Manual" xsi:type="string">manual</item> + </field> + <field name="catalog/layered_navigation/price_range_step" xsi:type="array"> + <item name="scope" xsi:type="string">default</item> + <item name="scope_id" xsi:type="number">0</item> + <item name="value" xsi:type="string">10</item> + </field> + <field name="catalog/layered_navigation/price_range_max_intervals" xsi:type="array"> + <item name="scope" xsi:type="string">default</item> + <item name="scope_id" xsi:type="number">0</item> + <item name="value" xsi:type="string">10</item> + </field> + </dataset> + <dataset name="layered_navigation_manual_range_10_rollback"> + <field name="catalog/layered_navigation/display_product_count" xsi:type="array"> + <item name="scope" xsi:type="string">default</item> + <item name="scope_id" xsi:type="number">0</item> + <item name="value" label="Yes" xsi:type="string">1</item> + </field> + <field name="catalog/layered_navigation/price_range_calculation" xsi:type="array"> + <item name="scope" xsi:type="string">default</item> + <item name="scope_id" xsi:type="number">0</item> + <item name="value" label="Automatic (equalize price ranges)" xsi:type="string">auto</item> + </field> + </dataset> + </repository> +</config> diff --git a/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/TestCase/FilterProductListTest.php b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/TestCase/FilterProductListTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dea532e69cf26dfe81ce7bb3fa281bf26a077dd8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/TestCase/FilterProductListTest.php @@ -0,0 +1,73 @@ +<?php + +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\LayeredNavigation\Test\TestCase; + +use Magento\Catalog\Test\Fixture\CatalogProductSimple; +use Magento\Catalog\Test\Fixture\Category; +use Magento\Mtf\TestCase\Injectable; + +/** + * Preconditions: + * 1. Setup Layered Navigation configuration. + * + * Steps: + * 1. Create category. + * 2. Create product with created category. + * 3. Perform all assertions. + * + * @group Layered_Navigation_(MX) + * @ZephyrId MAGETWO-12419 + */ +class FilterProductListTest extends Injectable +{ + /* tags */ + const DOMAIN = 'MX'; + const TEST_TYPE = 'acceptance_test'; + /* end tags */ + + /** + * Configuration setting. + * + * @var string + */ + protected $configData; + + /** + * Filtering product in the Frontend via layered navigation. + * + * @param string $configData + * @param Category $category + * @return array + */ + public function test($configData, Category $category) + { + $this->configData = $configData; + + // Preconditions + $this->objectManager->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => $this->configData] + )->run(); + + // Steps + $category->persist(); + } + + /** + * Clean data after running test. + * + * @return void + */ + public function tearDown() + { + $this->objectManager->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => $this->configData, 'rollback' => true] + )->run(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/TestCase/FilterProductListTest.xml b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/TestCase/FilterProductListTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..4cfbc8d6397ff7d52133d0a2c70d129c06825b01 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/LayeredNavigation/Test/TestCase/FilterProductListTest.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\LayeredNavigation\Test\TestCase\FilterProductListTest"> + <variation name="FilterProductListTestVariation1"> + <data name="configData" xsi:type="string">layered_navigation_manual_range_10</data> + <data name="category/dataSet" xsi:type="string">default_anchor_subcategory</data> + <data name="category/data/category_products/dataSet" xsi:type="string">catalogProductSimple::product_20_dollar, configurableProduct::filterable_two_options_with_zero_price</data> + <data name="layeredNavigation" xsi:type="array"> + <item name="filters_0" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="title" xsi:type="string">Price</item> + <item name="linkPattern" xsi:type="string">`^.+10\.00 - .+19\.99 1$`m</item> + <item name="products" xsi:type="string">product_1</item> + </item> + </item> + <item name="filters_1" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="title" xsi:type="string">attribute_dropdown</item> + <item name="linkPattern" xsi:type="string">`^option_0_[0-9]+ 1$`m</item> + <item name="products" xsi:type="string">product_1</item> + </item> + </item> + </data> + <data name="tag" xsi:type="string">test_type:acceptance_test</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForAssignedProducts" /> + <constraint name="Magento\LayeredNavigation\Test\Constraint\AssertFilterProductList" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Edit/CustomerForm.xml b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Edit/CustomerForm.xml index c7a99a1c233ca0d32fb2e2703edf7b4c7f502484..32892c7138a7989b8d85d8c1092b80464054946c 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Edit/CustomerForm.xml +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Adminhtml/Edit/CustomerForm.xml @@ -8,7 +8,7 @@ <tabs> <product_reviews> <class>\Magento\Review\Test\Block\Adminhtml\Customer\Edit\Tab\Reviews</class> - <selector>#tab_reviews</selector> + <selector>#tab_block_reviews</selector> <strategy>css selector</strategy> </product_reviews> </tabs> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Coupons.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Coupons.php index e118bac1958fb0b3c9d0906bdafe181e157a9a7b..0a350725839b9e8833b90dda8003c051b0c7293c 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Coupons.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Coupons.php @@ -7,7 +7,7 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\Create; use Magento\Backend\Test\Block\Widget\Form; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\Mtf\Client\Locator; /** @@ -32,10 +32,10 @@ class Coupons extends Form /** * Enter discount code and click apply button. * - * @param SalesRuleInjectable $code + * @param SalesRule $code * @return void */ - public function applyCouponCode(SalesRuleInjectable $code) + public function applyCouponCode(SalesRule $code) { $this->_rootElement->find($this->couponCode)->setValue($code->getCouponCode()); $this->_rootElement->find($this->applyButton, Locator::SELECTOR_XPATH)->click(); diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/CouponCode.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/CouponCode.php index b3d081c56d4c759fe4728523de1732c42f1477d0..0a28aff4f63e99585c420f30ca03fcd9031e1a4e 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/CouponCode.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/CouponCode.php @@ -6,7 +6,7 @@ namespace Magento\Sales\Test\Fixture\OrderInjectable; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\Fixture\DataSource; @@ -24,12 +24,12 @@ class CouponCode extends DataSource public function __construct(FixtureFactory $fixtureFactory, array $data, array $params = []) { $this->params = $params; - if (isset($data['value']) && $data['value'] instanceof SalesRuleInjectable) { + if (isset($data['value']) && $data['value'] instanceof SalesRule) { $this->data = $data['value']; return; } if (isset($data['dataSet'])) { - $salesRule = $fixtureFactory->createByCode('salesRuleInjectable', ['dataSet' => $data['dataSet']]); + $salesRule = $fixtureFactory->createByCode('salesRule', ['dataSet' => $data['dataSet']]); $salesRule->persist(); $this->data = $salesRule; } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Curl.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Curl.php index e98f4ba0afff567f479384c0c7eaecef6543505d..7d993cb5f0094f6f9c9982314b44c83240402f88 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Curl.php @@ -11,7 +11,7 @@ use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct; use Magento\Customer\Test\Fixture\Customer; use Magento\Downloadable\Test\Fixture\DownloadableProduct; use Magento\Sales\Test\Fixture\OrderInjectable; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\Mtf\Fixture\FixtureInterface; use Magento\Mtf\Handler\Curl as AbstractCurl; use Magento\Mtf\Util\Protocol\CurlInterface; @@ -111,10 +111,10 @@ class Curl extends AbstractCurl implements OrderInjectableInterface /** * Prepare coupon data. * - * @param SalesRuleInjectable $data + * @param SalesRule $data * @return array */ - protected function prepareCouponCode(SalesRuleInjectable $data) + protected function prepareCouponCode(SalesRule $data) { return ['order' => ['coupon' => ['code' => $data->getCouponCode()]]]; } diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php index 1b573901d93ca029d529bf6c812e436b43d0ee05..a9307ce8132134ef2b9fde5dd5aa3e2f43aaffdd 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php @@ -15,7 +15,7 @@ use Magento\Customer\Test\Fixture\Address; use Magento\Customer\Test\Fixture\Customer; use Magento\Customer\Test\Page\CustomerAccountLogin; use Magento\Customer\Test\Page\CustomerAccountLogout; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\Mtf\Constraint\AbstractConstraint; /** @@ -121,8 +121,8 @@ abstract class AssertCartPriceRuleApplying extends AbstractConstraint * @param CatalogCategoryView $catalogCategoryView * @param CatalogProductView $catalogProductView * @param Customer $customer - * @param SalesRuleInjectable $salesRule - * @param SalesRuleInjectable $salesRuleOrigin + * @param SalesRule $salesRule + * @param SalesRule $salesRuleOrigin * @param array $productQuantity * @param CatalogProductSimple $productForSalesRule1 * @param CatalogProductSimple $productForSalesRule2 @@ -141,8 +141,8 @@ abstract class AssertCartPriceRuleApplying extends AbstractConstraint CatalogCategoryView $catalogCategoryView, CatalogProductView $catalogProductView, Customer $customer, - SalesRuleInjectable $salesRule, - SalesRuleInjectable $salesRuleOrigin, + SalesRule $salesRule, + SalesRule $salesRuleOrigin, array $productQuantity, CatalogProductSimple $productForSalesRule1, CatalogProductSimple $productForSalesRule2 = null, diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php index ccd77f877ced270b43d7bcc9f2081422676f0b58..d8a6445267051487c7f813a13dc62be1c8fd6981 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleForm.php @@ -6,7 +6,7 @@ namespace Magento\SalesRule\Test\Constraint; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteEdit; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteIndex; use Magento\Mtf\Constraint\AbstractConstraint; @@ -34,15 +34,15 @@ class AssertCartPriceRuleForm extends AbstractConstraint * * @param PromoQuoteIndex $promoQuoteIndex * @param PromoQuoteEdit $promoQuoteEdit - * @param SalesRuleInjectable $salesRule - * @param SalesRuleInjectable $salesRuleOrigin + * @param SalesRule $salesRule + * @param SalesRule $salesRuleOrigin * @return void */ public function processAssert( PromoQuoteIndex $promoQuoteIndex, PromoQuoteEdit $promoQuoteEdit, - SalesRuleInjectable $salesRule, - SalesRuleInjectable $salesRuleOrigin = null + SalesRule $salesRule, + SalesRule $salesRuleOrigin = null ) { $filter = [ 'name' => $salesRule->hasData('name') ? $salesRule->getName() : $salesRuleOrigin->getName(), diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleIsNotPresentedInGrid.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleIsNotPresentedInGrid.php index 4c2fd8856a08fdd1af69c5594124fef9443166f4..a0914721420c86595f74dd6b16a487175e935d74 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleIsNotPresentedInGrid.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleIsNotPresentedInGrid.php @@ -6,7 +6,7 @@ namespace Magento\SalesRule\Test\Constraint; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteIndex; use Magento\Mtf\Constraint\AbstractConstraint; @@ -19,10 +19,10 @@ class AssertCartPriceRuleIsNotPresentedInGrid extends AbstractConstraint * Assert that sales rule is not present in cart price rules grid. * * @param PromoQuoteIndex $promoQuoteIndex - * @param SalesRuleInjectable $salesRule + * @param SalesRule $salesRule * @return void */ - public function processAssert(PromoQuoteIndex $promoQuoteIndex, SalesRuleInjectable $salesRule) + public function processAssert(PromoQuoteIndex $promoQuoteIndex, SalesRule $salesRule) { \PHPUnit_Framework_Assert::assertFalse( $promoQuoteIndex->getPromoQuoteGrid()->isRowVisible(['name' => $salesRule->getName()]), diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRuleInjectable.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRule.xml similarity index 90% rename from dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRuleInjectable.xml rename to dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRule.xml index 25f432794e8432456a08e315988cfe84f60525fb..9008a93b8a36b6f82c5115afc176f113495742bc 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRuleInjectable.xml +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRule.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd"> - <fixture name="salesRuleInjectable" module="Magento_SalesRule" type="flat" entity_type="salesrule" collection="Magento\SalesRule\Model\Resource\Rule\Collection" repository_class="Magento\SalesRule\Test\Repository\SalesRuleInjectable" handler_interface="Magento\SalesRule\Test\Handler\SalesRuleInjectable\SalesRuleInjectableInterface" class="Magento\SalesRule\Test\Fixture\SalesRuleInjectable"> + <fixture name="salesRule" module="Magento_SalesRule" type="flat" entity_type="salesrule" collection="Magento\SalesRule\Model\Resource\Rule\Collection" repository_class="Magento\SalesRule\Test\Repository\SalesRule" handler_interface="Magento\SalesRule\Test\Handler\SalesRule\SalesRuleInterface" class="Magento\SalesRule\Test\Fixture\SalesRule"> <dataset name="default"> <field name="name" xsi:type="string">Default price rule %isolation%</field> <field name="is_active" xsi:type="string">Active</field> @@ -36,7 +36,7 @@ <field name="is_active" group="rule_information"> <default_value xsi:type="string">Active</default_value> </field> - <field name="conditions_serialized" group="conditions" source="Magento\SalesRule\Test\Fixture\SalesRuleInjectable\ConditionsSerialized" /> + <field name="conditions_serialized" group="conditions" source="Magento\SalesRule\Test\Fixture\SalesRule\ConditionsSerialized" /> <field name="actions_serialized" group="actions" /> <field name="stop_rules_processing" group="actions"> <default_value xsi:type="string">1</default_value> diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRuleInjectable/ConditionsSerialized.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRule/ConditionsSerialized.php similarity index 94% rename from dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRuleInjectable/ConditionsSerialized.php rename to dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRule/ConditionsSerialized.php index 4d9c65cff5333e179f7dc06f72f857f5da9baf54..d323abf4b46bd36de6a57e976c5bf1f7c8fa384d 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRuleInjectable/ConditionsSerialized.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Fixture/SalesRule/ConditionsSerialized.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +namespace Magento\SalesRule\Test\Fixture\SalesRule; use Magento\Mtf\Fixture\DataSource; diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRuleInjectable/Curl.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php similarity index 97% rename from dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRuleInjectable/Curl.php rename to dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php index 2543ccdf8197195b9cdbdc2bdb6444ef5903a784..d1c4bdee2f717d441fa26222e1eeea5045072894 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRuleInjectable/Curl.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\SalesRule\Test\Handler\SalesRuleInjectable; +namespace Magento\SalesRule\Test\Handler\SalesRule; use Magento\Backend\Test\Handler\Conditions; use Magento\Mtf\Fixture\FixtureInterface; @@ -15,7 +15,7 @@ use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator; /** * Curl handler for creating sales rule. */ -class Curl extends Conditions implements SalesRuleInjectableInterface +class Curl extends Conditions implements SalesRuleInterface { /** * Map of type parameter. diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRuleInjectable/SalesRuleInjectableInterface.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/SalesRuleInterface.php similarity index 61% rename from dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRuleInjectable/SalesRuleInjectableInterface.php rename to dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/SalesRuleInterface.php index 0a9c2598e8c49b16841c1efd0fda60e4d1d1d248..d638e854cf27339db2118d4ea9c9f5980ce3139b 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRuleInjectable/SalesRuleInjectableInterface.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/SalesRuleInterface.php @@ -4,14 +4,14 @@ * See COPYING.txt for license details. */ -namespace Magento\SalesRule\Test\Handler\SalesRuleInjectable; +namespace Magento\SalesRule\Test\Handler\SalesRule; use Magento\Mtf\Handler\HandlerInterface; /** * Interface SalesRuleInterface. */ -interface SalesRuleInjectableInterface extends HandlerInterface +interface SalesRuleInterface extends HandlerInterface { // } diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRuleInjectable.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml similarity index 99% rename from dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRuleInjectable.xml rename to dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml index 02d81f565a253de17ec04662a14bf162c330b256..897aa57c1bf7ff47a3b61b9d51e4b8782966a8ee 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRuleInjectable.xml +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> - <repository class="Magento\SalesRule\Test\Repository\SalesRuleInjectable"> + <repository class="Magento\SalesRule\Test\Repository\SalesRule"> <dataset name="active_sales_rule_with_percent_price_discount_coupon"> <field name="name" xsi:type="string">Shopping Cart Price Rule with Specific Coupon %isolation%</field> <field name="description" xsi:type="string">Description for Cart Price Rule</field> diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php index 24bafea36fbe42b87673f83accf39b5a70ddc666..e82c3e9bcc2c216a1185d1cb3c77f0ac9d5d6124 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php @@ -6,7 +6,7 @@ namespace Magento\SalesRule\Test\TestCase; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteEdit; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteIndex; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteNew; @@ -115,10 +115,10 @@ class CreateSalesRuleEntityTest extends Injectable /** * Create Sales Rule Entity. * - * @param SalesRuleInjectable $salesRule + * @param SalesRule $salesRule * @return void */ - public function testCreateSalesRule(SalesRuleInjectable $salesRule) + public function testCreateSalesRule(SalesRule $salesRule) { // Preconditions $this->salesRuleName = $salesRule->getName(); diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php index 49f3e7655790d8cf6ec4842d2861cc55692e5a72..3dcf7ad8e3a6df646e81ade107440b57c8587887 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php @@ -6,7 +6,7 @@ namespace Magento\SalesRule\Test\TestCase; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteEdit; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteIndex; use Magento\Mtf\TestCase\Injectable; @@ -63,10 +63,10 @@ class DeleteSalesRuleEntityTest extends Injectable /** * Delete Sales Rule Entity. * - * @param SalesRuleInjectable $salesRule + * @param SalesRule $salesRule * @return void */ - public function testDeleteSalesRule(SalesRuleInjectable $salesRule) + public function testDeleteSalesRule(SalesRule $salesRule) { // Preconditions $salesRule->persist(); diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.php index ed72d923f05b1911611a38244d9f5e2b79c5d669..93e0e862805255e0f86bb8ccd131382acc2c280f 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.php @@ -6,7 +6,7 @@ namespace Magento\SalesRule\Test\TestCase; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteEdit; use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteIndex; use Magento\Mtf\Fixture\FixtureFactory; @@ -92,13 +92,13 @@ class UpdateSalesRuleEntityTest extends Injectable /** * Update Sales Rule Entity. * - * @param SalesRuleInjectable $salesRule - * @param SalesRuleInjectable $salesRuleOrigin + * @param SalesRule $salesRule + * @param SalesRule $salesRuleOrigin * @return void */ public function testUpdateSalesRule( - SalesRuleInjectable $salesRule, - SalesRuleInjectable $salesRuleOrigin + SalesRule $salesRule, + SalesRule $salesRuleOrigin ) { // Preconditions $salesRuleOrigin->persist(); diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnBackendStep.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnBackendStep.php index 7e193a4d0ab1cc570bbbebad6dedda8c57946c6d..709e2c1644b71675224dc3941c2e4d7a1bc3ff7e 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnBackendStep.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnBackendStep.php @@ -7,7 +7,7 @@ namespace Magento\SalesRule\Test\TestStep; use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\Mtf\TestStep\TestStepInterface; /** @@ -25,16 +25,16 @@ class ApplySalesRuleOnBackendStep implements TestStepInterface /** * SalesRule fixture. * - * @var SalesRuleInjectable + * @var SalesRule */ protected $salesRule; /** * @constructor * @param OrderCreateIndex $orderCreateIndex - * @param SalesRuleInjectable $salesRule + * @param SalesRule $salesRule */ - public function __construct(OrderCreateIndex $orderCreateIndex, SalesRuleInjectable $salesRule = null) + public function __construct(OrderCreateIndex $orderCreateIndex, SalesRule $salesRule = null) { $this->orderCreateIndex = $orderCreateIndex; $this->salesRule = $salesRule; diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnFrontendStep.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnFrontendStep.php index 6bff54ec11dee9b17a78f52478fff86e8652457d..49fedf0d5d16dd7b214105d42fb4cab24e55aaa8 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnFrontendStep.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/ApplySalesRuleOnFrontendStep.php @@ -7,7 +7,7 @@ namespace Magento\SalesRule\Test\TestStep; use Magento\Checkout\Test\Page\CheckoutCart; -use Magento\SalesRule\Test\Fixture\SalesRuleInjectable; +use Magento\SalesRule\Test\Fixture\SalesRule; use Magento\Mtf\TestStep\TestStepInterface; /** @@ -25,16 +25,16 @@ class ApplySalesRuleOnFrontendStep implements TestStepInterface /** * SalesRule fixture. * - * @var SalesRuleInjectable + * @var SalesRule */ protected $salesRule; /** * @constructor * @param CheckoutCart $checkoutCart - * @param SalesRuleInjectable $salesRule + * @param SalesRule $salesRule */ - public function __construct(CheckoutCart $checkoutCart, SalesRuleInjectable $salesRule = null) + public function __construct(CheckoutCart $checkoutCart, SalesRule $salesRule = null) { $this->checkoutCart = $checkoutCart; $this->salesRule = $salesRule; diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/CreateSalesRuleStep.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/CreateSalesRuleStep.php index c458bed8659ad8e8b3d2d381a1601ecfade3e163..bda908faf26778fa05dfb90b4dac909a3d6d4902 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/CreateSalesRuleStep.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/CreateSalesRuleStep.php @@ -51,7 +51,7 @@ class CreateSalesRuleStep implements TestStepInterface $result['salesRule'] = null; if ($this->salesRule !== null) { $salesRule = $this->fixtureFactory->createByCode( - 'salesRuleInjectable', + 'salesRule', ['dataSet' => $this->salesRule] ); $salesRule->persist(); diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/DeleteAllSalesRuleStep.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/DeleteAllSalesRuleStep.php index 0141a0506fd6e926987234027c894c7462c01245..98bf51e84f7c37fa0c7cf86af5024e0f7ceefe72 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/DeleteAllSalesRuleStep.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestStep/DeleteAllSalesRuleStep.php @@ -50,6 +50,7 @@ class DeleteAllSalesRuleStep implements TestStepInterface public function run() { $this->promoQuoteIndex->open(); + $this->promoQuoteIndex->getPromoQuoteGrid()->resetFilter(); while ($this->promoQuoteIndex->getPromoQuoteGrid()->isFirstRowVisible()) { $this->promoQuoteIndex->getPromoQuoteGrid()->openFirstRow(); $this->promoQuoteEdit->getFormPageActions()->delete(); diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/etc/curl/di.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/etc/curl/di.xml index 2591249e9e02850c5123b9c66a0652a7bd5cfa00..3416929d0ab44031cbb7bef4b0d3ac7628cf9139 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/etc/curl/di.xml +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/etc/curl/di.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> - <preference for="Magento\SalesRule\Test\Handler\SalesRuleInjectable\SalesRuleInjectableInterface" type="\Magento\SalesRule\Test\Handler\SalesRuleInjectable\Curl" /> + <preference for="Magento\SalesRule\Test\Handler\SalesRule\SalesRuleInterface" type="\Magento\SalesRule\Test\Handler\SalesRule\Curl" /> </config> diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php index b5631910c0d44a00f93df89cc540b56734348c1a..51476690a8897b2f9b745dc46fbab9c4a12a1955 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php @@ -11,15 +11,12 @@ use Magento\Catalog\Test\Page\Product\CatalogProductView; use Magento\Checkout\Test\Page\CheckoutCart; use Magento\Customer\Test\Fixture\Address; use Magento\Customer\Test\Fixture\Customer; -use Magento\Customer\Test\Page\CustomerAccountLogin; -use Magento\Customer\Test\Page\CustomerAccountLogout; use Magento\Tax\Test\Fixture\TaxRule; use Magento\Mtf\Client\BrowserInterface; use Magento\Mtf\Constraint\AbstractConstraint; use Magento\Mtf\Fixture\FixtureFactory; /** - * Class AssertTaxRuleApplying * Abstract class for implementing assert applying */ abstract class AssertTaxRuleApplying extends AbstractConstraint @@ -82,8 +79,6 @@ abstract class AssertTaxRuleApplying extends AbstractConstraint * * @param FixtureFactory $fixtureFactory * @param TaxRule $taxRule - * @param CustomerAccountLogin $customerAccountLogin - * @param CustomerAccountLogout $customerAccountLogout * @param Customer $customer * @param CatalogProductView $catalogProductView * @param CheckoutCart $checkoutCart @@ -92,14 +87,10 @@ abstract class AssertTaxRuleApplying extends AbstractConstraint * @param BrowserInterface $browser * @param TaxRule $initialTaxRule * @return void - * - * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function processAssert( FixtureFactory $fixtureFactory, TaxRule $taxRule, - CustomerAccountLogin $customerAccountLogin, - CustomerAccountLogout $customerAccountLogout, Customer $customer, CatalogProductView $catalogProductView, CheckoutCart $checkoutCart, @@ -134,9 +125,10 @@ abstract class AssertTaxRuleApplying extends AbstractConstraint ); $this->productSimple->persist(); // Customer login - $customerAccountLogout->open(); - $customerAccountLogin->open(); - $customerAccountLogin->getLoginBlock()->login($customer); + $this->objectManager->create( + 'Magento\Customer\Test\TestStep\LoginCustomerOnFrontendStep', + ['customer' => $customer] + )->run(); // Clearing shopping cart and adding product to shopping cart $checkoutCart->open()->getCartBlock()->clearShoppingCart(); $browser->open($_ENV['app_frontend_url'] . $this->productSimple->getUrlKey() . '.html'); diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxCalculationTest.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxCalculationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ddfd3ab0508cc3a90986eada1db016a526ba921e --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxCalculationTest.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Tax\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; +use Magento\Mtf\ObjectManager; + +/** + * Steps: + * 1. Log in as default admin user. + * 2. Go to Stores > Taxes > Tax Rules. + * 3. Click 'Add New Tax Rule' button. + * 4. Assign default rates to rule. + * 5. Save Tax Rate. + * 6. Go to Products > Catalog. + * 7. Add new product. + * 8. Fill data according to dataset. + * 9. Save product. + * 10. Go to Stores > Configuration. + * 11. Fill Tax configuration according to data set. + * 12. Save tax configuration. + * 13. Perform all assertions. + * + * @group Tax_(CS) + * @ZephyrId MAGETWO-27809 + */ +class TaxCalculationTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const DOMAIN = 'CS'; + /* end tags */ + + /** + * Skip failed tests. + * + * @return void + */ + public static function setUpBeforeClass() + { + self::markTestIncomplete("Epic: MAGETWO-30073"); + } + + /** + * Runs tax calculation test. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } + + /** + * Tear down after each test. + * + * @return void + */ + public function tearDown() + { + $this->objectManager->create('\Magento\Tax\Test\TestStep\DeleteAllTaxRulesStep')->run(); + $this->objectManager->create('\Magento\SalesRule\Test\TestStep\DeleteAllSalesRuleStep')->run(); + $this->objectManager->create('\Magento\CatalogRule\Test\TestStep\DeleteAllCatalogRulesStep')->run(); + + // TODO: Move set default configuration to "tearDownAfterClass" method after fix bug MAGETWO-29331 + $this->objectManager->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => 'default_tax_configuration'] + )->run(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxCalculationTest.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxCalculationTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..9891afcdf2d0fa727302f3c047f08bea83beb05f --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxCalculationTest.xml @@ -0,0 +1,301 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Tax\Test\TestCase\TaxCalculationTest"> + <variation name="TaxCalculationTestVariation1"> + <data name="description" xsi:type="string">Simple product tier price with sales rule, customer tax equals store tax and catalog price including tax</data> + <data name="configData" xsi:type="string">row_cat_incl_ship_excl_after_disc_on_excl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::simple_with_tier_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_equals_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">277.14</data> + <data name="prices/category_price_incl_tax" xsi:type="string">300.00</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">277.14</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">300.00</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">13.86</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">15.00</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">41.57</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">45.00</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">41.57</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">45.00</data> + <data name="prices/discount" xsi:type="string">20.79</data> + <data name="prices/shipping_excl_tax" xsi:type="string">15.00</data> + <data name="prices/shipping_incl_tax" xsi:type="string">16.24</data> + <data name="prices/tax" xsi:type="string">3.09</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">37.36</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">40.45</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation2"> + <data name="description" xsi:type="string">Simple product group price with sales rule, customer tax greater than store tax and catalog price excluding tax</data> + <data name="configData" xsi:type="string">row_cat_excl_ship_incl_before_disc_on_incl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::simple_with_group_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_greater_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/category_price_incl_tax" xsi:type="string">98.61</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">98.61</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">98.61</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">272.97</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">295.83</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">272.97</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">295.83</data> + <data name="prices/discount" xsi:type="string">147.92</data> + <data name="prices/shipping_excl_tax" xsi:type="string">13.86</data> + <data name="prices/shipping_incl_tax" xsi:type="string">15.02</data> + <data name="prices/tax" xsi:type="string">24.02</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">138.91</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">162.93</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation3"> + <data name="description" xsi:type="string">Simple product group price with sales rule, customer tax less than store tax and catalog price excluding tax</data> + <data name="configData" xsi:type="string">total_cat_excl_ship_incl_after_disc_on_excl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::simple_with_group_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_less_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/category_price_incl_tax" xsi:type="string">98.50</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">98.50</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">98.50</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">272.97</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">295.49</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">272.97</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">295.49</data> + <data name="prices/discount" xsi:type="string">136.49</data> + <data name="prices/shipping_excl_tax" xsi:type="string">13.84</data> + <data name="prices/shipping_incl_tax" xsi:type="string">14.98</data> + <data name="prices/tax" xsi:type="string">12.40</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">150.32</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">162.72</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation4"> + <data name="description" xsi:type="string">Simple product special price with sales rule, customer tax less than store tax and catalog price including tax</data> + <data name="configData" xsi:type="string">row_cat_incl_ship_excl_before_disc_on_incl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::product_with_special_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_less_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">83.05</data> + <data name="prices/category_price_incl_tax" xsi:type="string">89.90</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">83.05</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">89.90</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">83.05</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">89.90</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">249.15</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">269.70</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">249.15</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">269.70</data> + <data name="prices/discount" xsi:type="string">134.85</data> + <data name="prices/shipping_excl_tax" xsi:type="string">15.00</data> + <data name="prices/shipping_incl_tax" xsi:type="string">16.24</data> + <data name="prices/tax" xsi:type="string">21.79</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">129.30</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">151.09</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation5"> + <data name="description" xsi:type="string">Simple product tier price with sales rule, customer tax less than store tax and catalog price including tax</data> + <data name="configData" xsi:type="string">unit_cat_incl_ship_incl_before_disc_on_incl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::simple_with_tier_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_less_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">276.81</data> + <data name="prices/category_price_incl_tax" xsi:type="string">299.65</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">276.81</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">299.65</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">13.84</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">14.98</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">41.52</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">44.94</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">41.52</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">44.94</data> + <data name="prices/discount" xsi:type="string">22.47</data> + <data name="prices/shipping_excl_tax" xsi:type="string">13.84</data> + <data name="prices/shipping_incl_tax" xsi:type="string">14.98</data> + <data name="prices/tax" xsi:type="string">4.56</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">32.89</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">37.45</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation6"> + <data name="description" xsi:type="string">Simple product special price with sales rule, customer tax equals store tax and catalog price excluding tax</data> + <data name="configData" xsi:type="string">total_cat_excl_ship_incl_before_disc_on_incl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::product_with_special_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_equals_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">90.00</data> + <data name="prices/category_price_incl_tax" xsi:type="string">97.43</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">90.00</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">97.43</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">90.00</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">97.43</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">270.00</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">292.28</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">270.00</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">292.28</data> + <data name="prices/discount" xsi:type="string">146.15</data> + <data name="prices/shipping_excl_tax" xsi:type="string">13.86</data> + <data name="prices/shipping_incl_tax" xsi:type="string">15.00</data> + <data name="prices/tax" xsi:type="string">23.42</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">137.71</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">161.13</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation7"> + <data name="description" xsi:type="string">Simple product group price with sales rule, customer tax equals store tax and catalog price excluding tax</data> + <data name="configData" xsi:type="string">unit_cat_excl_ship_excl_after_disc_on_excl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::simple_with_group_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_equals_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/category_price_incl_tax" xsi:type="string">98.50</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">98.50</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">90.99</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">98.50</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">272.97</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">295.50</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">272.97</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">295.50</data> + <data name="prices/discount" xsi:type="string">136.49</data> + <data name="prices/shipping_excl_tax" xsi:type="string">15.00</data> + <data name="prices/shipping_incl_tax" xsi:type="string">16.24</data> + <data name="prices/tax" xsi:type="string">12.49</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">151.48</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">163.97</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation8"> + <data name="description" xsi:type="string">Simple product special price with sales rule, customer tax greater than store tax and catalog price including tax</data> + <data name="configData" xsi:type="string">total_cat_incl_ship_excl_before_disc_on_excl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::simple_with_group_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_greater_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">84.06</data> + <data name="prices/category_price_incl_tax" xsi:type="string">91.10</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">84.06</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">91.10</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">84.06</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">91.10</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">252.18</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">273.30</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">252.18</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">273.30</data> + <data name="prices/discount" xsi:type="string">126.09</data> + <data name="prices/shipping_excl_tax" xsi:type="string">15.00</data> + <data name="prices/shipping_incl_tax" xsi:type="string">16.26</data> + <data name="prices/tax" xsi:type="string">22.38</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">141.09</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">163.47</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation9"> + <data name="description" xsi:type="string">Simple product tier price with sales rule, customer tax greater than store tax and catalog price excluding tax</data> + <data name="configData" xsi:type="string">total_cat_excl_ship_incl_after_disc_on_incl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::simple_with_tier_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_greater_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">300.00</data> + <data name="prices/category_price_incl_tax" xsi:type="string">325.13</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">300.00</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">325.13</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">15.00</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">16.26</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">45.00</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">48.77</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">45.00</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">48.77</data> + <data name="prices/discount" xsi:type="string">24.39</data> + <data name="prices/shipping_excl_tax" xsi:type="string">13.86</data> + <data name="prices/shipping_incl_tax" xsi:type="string">15.02</data> + <data name="prices/tax" xsi:type="string">2.89</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">34.47</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">37.36</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + <variation name="TaxCalculationTestVariation10"> + <data name="description" xsi:type="string">Simple product special price with sales rule, customer tax greater than store tax and catalog price excluding tax</data> + <data name="configData" xsi:type="string">unit_cat_excl_ship_incl_after_disc_on_excl, display_excluding_including_tax</data> + <data name="product" xsi:type="string">catalogProductSimple::product_with_special_price_and_category</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="taxRule" xsi:type="string">customer_greater_store_rate</data> + <data name="customer/dataSet" xsi:type="string">johndoe_unique</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">90.00</data> + <data name="prices/category_price_incl_tax" xsi:type="string">97.54</data> + <data name="prices/product_view_price_excl_tax" xsi:type="string">90.00</data> + <data name="prices/product_view_price_incl_tax" xsi:type="string">97.54</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">90.00</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">97.54</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">270.00</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">292.62</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">270.00</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">292.62</data> + <data name="prices/discount" xsi:type="string">135.00</data> + <data name="prices/shipping_excl_tax" xsi:type="string">13.86</data> + <data name="prices/shipping_incl_tax" xsi:type="string">15.02</data> + <data name="prices/tax" xsi:type="string">12.47</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">148.86</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">161.33</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxCalculationAfterCheckoutExcludingIncludingTax" /> + <constraint name="Magento\Tax\Test\Constraint\AssertOrderTaxOnBackendExcludingIncludingTax" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b67edd7a4c1787025b0b0b45b126f3c3996427e4 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.php @@ -0,0 +1,160 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Tax\Test\TestCase; + +use Magento\Catalog\Test\Fixture\CatalogProductSimple; +use Magento\CatalogRule\Test\Fixture\CatalogRule; +use Magento\Customer\Test\Fixture\Customer; +use Magento\SalesRule\Test\Fixture\SalesRule; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\TestCase\Injectable; + +/** + * Steps: + * 1. Log in as default admin user. + * 2. Go to Stores > Taxes > Tax Rules. + * 3. Click 'Add New Tax Rule' button. + * 4. Assign 3 different rates for different addresses + * 5. Save Tax Rate. + * 6. Go to Products > Catalog. + * 7. Add new product. + * 8. Fill data according to dataset. + * 9. Save product. + * 10. Go to Stores > Configuration. + * 11. Fill Tax configuration according to data set. + * 12. Save tax configuration. + * 13. Register two customers on front end that will match two different rates + * 14. Login with each customer and verify prices + * + * @group Tax_(CS) + * @ZephyrId MAGETWO-29052 + */ +class TaxWithCrossBorderTest extends Injectable +{ + /* tags */ + const MVP = 'yes'; + const DOMAIN = 'CS'; + /* end tags */ + + /** + * Fixture SalesRule. + * + * @var SalesRule + */ + protected $salesRule; + + /** + * Fixture CatalogRule. + * + * @var CatalogRule + */ + protected $catalogRule; + + /** + * Fixture factory. + * + * @var FixtureFactory + */ + protected $fixtureFactory; + + /** + * Prepare data. + * + * @param FixtureFactory $fixtureFactory + * @return array + */ + public function __prepare(FixtureFactory $fixtureFactory) + { + $this->fixtureFactory = $fixtureFactory; + + return ['customers' => $this->createCustomers()]; + } + + /** + * Injection data. + * + * @return void + */ + public function __inject() + { + // TODO: Move test set up to "__prepare" method after fix bug MAGETWO-29331 + $taxRule = $this->fixtureFactory->createByCode('taxRule', ['dataSet' => 'cross_border_tax_rule']); + $taxRule->persist(); + } + + /** + * Create customers. + * + * @return array $customers + */ + protected function createCustomers() + { + $customersData = ['johndoe_unique_TX', 'johndoe_unique']; + $customers = []; + foreach ($customersData as $customerData) { + $customer = $this->fixtureFactory->createByCode('customer', ['dataSet' => $customerData]); + $customer->persist(); + $customers[] = $customer; + } + return $customers; + } + + /** + * Test product prices with tax. + * + * @param CatalogProductSimple $product + * @param string $configData + * @param SalesRule $salesRule [optional] + * @param CatalogRule $catalogRule [optional] + * @return void + */ + public function test( + CatalogProductSimple $product, + $configData, + SalesRule $salesRule = null, + CatalogRule $catalogRule = null + ) { + //Preconditions + if ($salesRule !== null) { + $salesRule->persist(); + $this->salesRule = $salesRule; + } + if ($catalogRule !== null) { + $catalogRule->persist(); + $this->catalogRule = $catalogRule; + } + $this->objectManager->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => $configData] + )->run(); + $product->persist(); + } + + /** + * Tear down after test. + * + * @return void + */ + public function tearDown() + { + if (isset($this->salesRule)) { + $this->objectManager->create('Magento\SalesRule\Test\TestStep\DeleteAllSalesRuleStep')->run(); + $this->salesRule = null; + } + if (isset($this->catalogRule)) { + $this->objectManager->create('\Magento\CatalogRule\Test\TestStep\DeleteAllCatalogRulesStep')->run(); + $this->catalogRule = null; + } + + // TODO: Move set default configuration to "tearDownAfterClass" method after fix bug MAGETWO-29331 + $this->objectManager->create('Magento\Tax\Test\TestStep\DeleteAllTaxRulesStep')->run(); + $this->objectManager->create( + 'Magento\Config\Test\TestStep\SetupConfigurationStep', + ['configData' => 'default_tax_configuration'] + )->run(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..82218491cf409382415251e998b235429a4364c5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxWithCrossBorderTest.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Tax\Test\TestCase\TaxWithCrossBorderTest"> + <variation name="TaxWithCrossBorderTestVariation1"> + <data name="product/dataSet" xsi:type="string">with_one_custom_option_and_category</data> + <data name="configData" xsi:type="string">cross_border_enabled_price_incl_tax, display_excluding_including_tax</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderApplied" /> + </variation> + <variation name="TaxWithCrossBorderTestVariation2"> + <data name="product/dataSet" xsi:type="string">product_with_category</data> + <data name="salesRule/dataSet" xsi:type="string">cart_rule</data> + <data name="configData" xsi:type="string">cross_border_enabled_price_incl_tax, display_excluding_including_tax</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderApplied" /> + </variation> + <variation name="TaxWithCrossBorderTestVariation3"> + <data name="product/dataSet" xsi:type="string">product_with_category</data> + <data name="catalogRule/dataSet" xsi:type="string">catalog_price_rule_priority_0</data> + <data name="configData" xsi:type="string">cross_border_enabled_price_incl_tax, display_excluding_including_tax</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderApplied" /> + </variation> + <variation name="TaxWithCrossBorderTestVariation4"> + <data name="product/dataSet" xsi:type="string">product_with_special_price_and_category</data> + <data name="configData" xsi:type="string">cross_border_enabled_price_incl_tax, display_excluding_including_tax</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderApplied" /> + </variation> + <variation name="TaxWithCrossBorderTestVariation5"> + <data name="product/dataSet" xsi:type="string">product_with_category</data> + <data name="configData" xsi:type="string">cross_border_enabled_price_excl_tax, display_excluding_including_tax</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderNotApplied" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestStep/DeleteAllTaxRulesStep.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestStep/DeleteAllTaxRulesStep.php index 69b0cb8e48754397a8a3d56873fcc721f7e6269a..d24b2ca4c4de8cd5cb362704b3c78c2ad4905fb4 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestStep/DeleteAllTaxRulesStep.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestStep/DeleteAllTaxRulesStep.php @@ -51,6 +51,7 @@ class DeleteAllTaxRulesStep implements TestStepInterface public function run() { $this->taxRuleIndexPage->open(); + $this->taxRuleIndexPage->getTaxRuleGrid()->resetFilter(); while ($this->taxRuleIndexPage->getTaxRuleGrid()->isFirstRowVisible()) { $this->taxRuleIndexPage->getTaxRuleGrid()->openFirstRow(); $this->taxRuleNewPage->getFormPageActions()->delete(); diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/etc/testcase.xml new file mode 100644 index 0000000000000000000000000000000000000000..c47afe1a6a889a0df215473b24539396e0ff8b77 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/etc/testcase.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/TestCase/etc/testcase.xsd"> + <scenario name="TaxCalculationTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createSalesRule" /> + <step name="createSalesRule" module="Magento_SalesRule" next="createCatalogRule" /> + <step name="createCatalogRule" module="Magento_CatalogRule" next="createTaxRule" /> + <step name="createTaxRule" module="Magento_Tax" next="createProduct" /> + <step name="createProduct" module="Magento_Catalog" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="loginCustomerOnFrontend" /> + <step name="loginCustomerOnFrontend" module="Magento_Customer" /> + </scenario> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml index 5351224a4f52e4bc04b92617f30d0190b5963fb3..f6c7bd8341526c7fa4e6f48a79f020fb5830b2b8 100644 --- a/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0" ?> <!-- /** * Copyright © 2015 Magento. All rights reserved. diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Adminhtml/Edit/CustomerForm.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Adminhtml/Edit/CustomerForm.xml index c00338cd02750df3c73fca736d49307814d8e286..d6a8abbf78b151df64f7fee7e5dcd34d1674c15a 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Adminhtml/Edit/CustomerForm.xml +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Adminhtml/Edit/CustomerForm.xml @@ -8,7 +8,7 @@ <tabs> <wishlist> <class>\Magento\Wishlist\Test\Block\Adminhtml\Customer\Edit\Tab\Wishlist</class> - <selector>#tab_wishlist</selector> + <selector>#tab_block_wishlist</selector> <strategy>css selector</strategy> </wishlist> </tabs> diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml index 1cf13be71e2cd00324fbc5303d2a6bd31230fa33..d88f6d3054641ffa76b70d4b5593bcd59f3aede1 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml @@ -27,7 +27,7 @@ <constraint name="Magento\Wishlist\Test\Constraint\AssertWishlistIsEmpty" /> </variation> <variation name="AddProductsToCartFromCustomerWishlistOnFrontendTestVariation4"> - <data name="products" xsi:type="string">groupedProduct::three_simple_products_default_qty</data> + <data name="products" xsi:type="string">groupedProduct::three_simple_products</data> <data name="qty" xsi:type="string">-</data> <constraint name="Magento\Checkout\Test\Constraint\AssertProductQtyInShoppingCart" /> <constraint name="Magento\Wishlist\Test\Constraint\AssertProductsIsAbsentInWishlist" /> diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php index cce7949f993f63e0312573a558e50510fee1fc84..2b96619bcae14f8186d73bd61782a213238bd33e 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php @@ -11,34 +11,26 @@ use Magento\Catalog\Test\Page\Product\CatalogProductView; use Magento\Cms\Test\Page\CmsIndex; use Magento\Customer\Test\Fixture\Customer; use Magento\Customer\Test\Page\CustomerAccountIndex; -use Magento\Customer\Test\Page\CustomerAccountLogin; -use Magento\Customer\Test\Page\CustomerAccountLogout; use Magento\Wishlist\Test\Page\WishlistIndex; use Magento\Wishlist\Test\Page\WishlistShare; use Magento\Mtf\Client\BrowserInterface; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for ShareWishlistEntity - * - * Test Flow: - * * Preconditions: - * 1. Create Customer Account - * 2. Create product + * 1. Create Customer Account. + * 2. Create product. * * Steps: - * 1. Login to frontend as a Customer - * 2. Add product to Wish List - * 3. Click "Share Wish List" button - * 4. Fill in all data according to data set - * 5. Click "Share Wishlist" button - * 6. Perform all assertions + * 1. Login to frontend as a Customer. + * 2. Add product to Wish List. + * 3. Click "Share Wish List" button. + * 4. Fill in all data according to data set. + * 5. Click "Share Wishlist" button. + * 6. Perform all assertions. * * @group Wishlist_(CS) * @ZephyrId MAGETWO-23394 - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShareWishlistEntityTest extends Injectable { @@ -49,56 +41,42 @@ class ShareWishlistEntityTest extends Injectable /* end tags */ /** - * Cms index page + * Cms index page. * * @var CmsIndex */ protected $cmsIndex; /** - * Customer login page - * - * @var CustomerAccountLogin - */ - protected $customerAccountLogin; - - /** - * Customer account index page + * Customer account index page. * * @var CustomerAccountIndex */ protected $customerAccountIndex; /** - * Product view page + * Product view page. * * @var CatalogProductView */ protected $catalogProductView; /** - * Page CustomerAccountLogout - * - * @var CustomerAccountLogout - */ - protected $customerAccountLogout; - - /** - * Wishlist index page + * Wishlist index page. * * @var WishlistIndex */ protected $wishlistIndex; /** - * Wishlist share page + * Wishlist share page. * * @var WishlistShare */ protected $wishlistShare; /** - * Prepare data + * Prepare data. * * @param Customer $customer * @param CatalogProductSimple $product @@ -118,12 +96,10 @@ class ShareWishlistEntityTest extends Injectable } /** - * Injection data + * Inject pages. * * @param CmsIndex $cmsIndex - * @param CustomerAccountLogin $customerAccountLogin * @param CustomerAccountIndex $customerAccountIndex - * @param CustomerAccountLogout $customerAccountLogout * @param CatalogProductView $catalogProductView * @param WishlistIndex $wishlistIndex * @param WishlistShare $wishlistShare @@ -131,24 +107,20 @@ class ShareWishlistEntityTest extends Injectable */ public function __inject( CmsIndex $cmsIndex, - CustomerAccountLogin $customerAccountLogin, CustomerAccountIndex $customerAccountIndex, - CustomerAccountLogout $customerAccountLogout, CatalogProductView $catalogProductView, WishlistIndex $wishlistIndex, WishlistShare $wishlistShare ) { $this->cmsIndex = $cmsIndex; - $this->customerAccountLogin = $customerAccountLogin; $this->customerAccountIndex = $customerAccountIndex; - $this->customerAccountLogout = $customerAccountLogout; $this->catalogProductView = $catalogProductView; $this->wishlistIndex = $wishlistIndex; $this->wishlistShare = $wishlistShare; } /** - * Share wish list + * Share wish list. * * @param BrowserInterface $browser * @param Customer $customer @@ -174,27 +146,16 @@ class ShareWishlistEntityTest extends Injectable } /** - * Login customer + * Login customer. * * @param Customer $customer * @return void */ protected function loginCustomer(Customer $customer) { - $this->cmsIndex->open(); - if (!$this->cmsIndex->getLinksBlock()->isLinkVisible('Log Out')) { - $this->cmsIndex->getLinksBlock()->openLink("Log In"); - $this->customerAccountLogin->getLoginBlock()->login($customer); - } - } - - /** - * Log out after test - * - * @return void - */ - public function tearDown() - { - $this->customerAccountLogout->open(); + $this->objectManager->create( + 'Magento\Customer\Test\TestStep\LoginCustomerOnFrontendStep', + ['customer' => $customer] + )->run(); } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.xml index 59dccc42d293c1a3a1259565da59e9408c390de5..8dd654cf89bbd1065185ba2a345c5fe44f3cf65f 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.xml @@ -6,11 +6,11 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Wishlist\Test\TestCase\ShareWishlistEntityTest"> - <variation name="ShareWishlistEntityTestVariation1"> - <data name="sharingInfo/emails" xsi:type="string">JohnDoe123456789@example.com,JohnDoe987654321@example.com,JohnDoe123456abc@example.com</data> - <data name="sharingInfo/message" xsi:type="string">Sharing message.</data> - <constraint name="Magento\Wishlist\Test\Constraint\AssertWishlistShareMessage"/> - </variation> - </testCase> + <testCase name="Magento\Wishlist\Test\TestCase\ShareWishlistEntityTest"> + <variation name="ShareWishlistEntityTestVariation1"> + <data name="sharingInfo/emails" xsi:type="string">JohnDoe123456789@example.com,JohnDoe987654321@example.com,JohnDoe123456abc@example.com</data> + <data name="sharingInfo/message" xsi:type="string">Sharing message.</data> + <constraint name="Magento\Wishlist\Test\Constraint\AssertWishlistShareMessage" /> + </variation> + </testCase> </config> diff --git a/dev/tests/functional/utils/config/ee_modules.yml.dist b/dev/tests/functional/utils/config/ee_modules.yml.dist deleted file mode 100644 index 33bd56450a7a26ceb8241a97495dbc1c23675c6e..0000000000000000000000000000000000000000 --- a/dev/tests/functional/utils/config/ee_modules.yml.dist +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright © 2015 Magento. All rights reserved. -# See COPYING.txt for license details. -- Magento_Backend -- Magento_Catalog -- Magento_Customer \ No newline at end of file diff --git a/dev/tests/functional/utils/config/generator_config.yml.dist b/dev/tests/functional/utils/config/generator_config.yml.dist deleted file mode 100644 index 14dffd2306b796de983017366d6b6b26e2f863e9..0000000000000000000000000000000000000000 --- a/dev/tests/functional/utils/config/generator_config.yml.dist +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright © 2015 Magento. All rights reserved. -# See COPYING.txt for license details. -# Generator running options, in case "generate_specified_modules" is set to "yes" then specified file is used -generate_specified_modules: no -specified_modules: dev\tests\functional\utils\config\ee_modules.yml.dist - -# Fallback path configurations -tests_fallback: - 1: - path: tests/app - -# Handler priority configuration -handler_fallback: - 1: Curl - 2: Direct - 3: Ui \ No newline at end of file diff --git a/dev/tests/integration/etc/install-config-mysql.php.dist b/dev/tests/integration/etc/install-config-mysql.php.dist index 0d8fb591eb14454b4d3c46045e3606ab6e47dea3..3cbe5eed4e976da6ad88238ad9a60a7fdb42c999 100644 --- a/dev/tests/integration/etc/install-config-mysql.php.dist +++ b/dev/tests/integration/etc/install-config-mysql.php.dist @@ -5,15 +5,15 @@ */ return [ - 'db_host' => 'localhost', - 'db_user' => 'root', - 'db_password' => '', - 'db_name' => 'magento_integration_tests', - 'db_prefix' => '', - 'backend_frontname' => 'backend', - 'admin_user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME, - 'admin_password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD, - 'admin_email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL, - 'admin_firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME, - 'admin_lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME, + 'db-host' => 'localhost', + 'db-user' => 'root', + 'db-password' => '', + 'db-name' => 'magento_integration_tests', + 'db-prefix' => '', + 'backend-frontname' => 'backend', + 'admin-user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME, + 'admin-password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD, + 'admin-email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL, + 'admin-firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME, + 'admin-lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME, ]; diff --git a/dev/tests/integration/etc/install-config-mysql.travis.php.dist b/dev/tests/integration/etc/install-config-mysql.travis.php.dist index a0e25fd80384beb21201843bca7e59a435a26c34..ac8eeb0bbbaccc5b2604d3a0e925c384afec1049 100644 --- a/dev/tests/integration/etc/install-config-mysql.travis.php.dist +++ b/dev/tests/integration/etc/install-config-mysql.travis.php.dist @@ -5,15 +5,15 @@ */ return [ - 'db_host' => '127.0.0.1', - 'db_user' => 'travis', - 'db_password' => '', - 'db_name' => 'magento_integration_tests', - 'db_prefix' => 'travis_', - 'backend_frontname' => 'backend', - 'admin_user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME, - 'admin_password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD, - 'admin_email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL, - 'admin_firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME, - 'admin_lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME, + 'db-host' => '127.0.0.1', + 'db-user' => 'travis', + 'db-password' => '', + 'db-name' => 'magento_integration_tests', + 'db-prefix' => 'travis_', + 'backend-frontname' => 'backend', + 'admin-user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME, + 'admin-password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD, + 'admin-email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL, + 'admin-firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME, + 'admin-lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME, ]; diff --git a/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php b/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php index 9854602a507fcc0045fcc2f5be86a85f96073b0d..3809d7f293849488c696e4631c03e6ed34e0de02 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php @@ -9,6 +9,8 @@ */ namespace Magento\TestFramework\Annotation; +use Magento\Framework\App\Config\ScopeConfigInterface; + class ConfigFixture { /** @@ -73,7 +75,7 @@ class ConfigFixture )->setValue( $configPath, $value, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ); } } else { diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php index 4d13da77e94c5767525784e06200107926193c3c..2ff3a1003e44f0d3d982e9aa6f01753fc7ca80c7 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Application.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php @@ -172,10 +172,10 @@ class Application $dbName = $dbInfo['dbname']; } else { $installConfig = $this->getInstallConfig(); - $host = $installConfig['db_host']; - $user = $installConfig['db_user']; - $password = $installConfig['db_password']; - $dbName = $installConfig['db_name']; + $host = $installConfig['db-host']; + $user = $installConfig['db-user']; + $password = $installConfig['db-password']; + $dbName = $installConfig['db-name']; } $this->_db = new Db\Mysql( $host, @@ -379,7 +379,7 @@ class Application * @see \Magento\Setup\Mvc\Bootstrap\InitParamListener::BOOTSTRAP_PARAM */ $this->_shell->execute( - 'php -f %s setup:uninstall -n --magento_init_params=%s', + 'php -f %s setup:uninstall -n --magento-init-params=%s', [BP . '/bin/magento', $this->getInitParamsQuery()] ); } @@ -466,7 +466,7 @@ class Application * Literal value is used instead of constant, because autoloader is not integrated with Magento Setup app * @see \Magento\Setup\Mvc\Bootstrap\InitParamListener::BOOTSTRAP_PARAM */ - $params['magento_init_params'] = $this->getInitParamsQuery(); + $params['magento-init-params'] = $this->getInitParamsQuery(); $result = []; foreach ($params as $key => $value) { if (!empty($value)) { diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php index 41453aa0becc0e2d32513736f2cb99ddc60e8854..b71bb17d945ccd42f693ed57588116e05c474dbb 100644 --- a/dev/tests/integration/framework/bootstrap.php +++ b/dev/tests/integration/framework/bootstrap.php @@ -8,6 +8,11 @@ use Magento\Framework\Autoload\AutoloaderRegistry; require_once __DIR__ . '/../../../../app/bootstrap.php'; require_once __DIR__ . '/autoload.php'; +$updateAppBootstrap = __DIR__ . '/../../../../update/app/bootstrap.php'; +if (file_exists($updateAppBootstrap)) { + require_once $updateAppBootstrap; +} + $testsBaseDir = dirname(__DIR__); $testsTmpDir = "{$testsBaseDir}/tmp"; $magentoBaseDir = realpath("{$testsBaseDir}/../../../"); diff --git a/dev/tests/integration/phpunit.xml.dist b/dev/tests/integration/phpunit.xml.dist index 7a9e365c8f15056e5060cd27827720e2d18d2fce..bd6cbffb247d64f6617eef5fc9c8ebaebb753b7e 100644 --- a/dev/tests/integration/phpunit.xml.dist +++ b/dev/tests/integration/phpunit.xml.dist @@ -18,6 +18,7 @@ </testsuite> <testsuite name="Magento Integration Tests"> <directory suffix="Test.php">testsuite</directory> + <directory suffix="Test.php">../../../update/dev/tests/integration/testsuite</directory> <exclude>testsuite/Magento/Test/Integrity</exclude> <exclude>testsuite/Magento/MemoryUsageTest.php</exclude> </testsuite> @@ -27,6 +28,7 @@ <whitelist addUncoveredFilesFromWhiteList="true"> <directory suffix=".php">../../../app/code/Magento</directory> <directory suffix=".php">../../../lib/internal/Magento</directory> + <directory suffix=".php">../../../update/app/code</directory> </whitelist> </filter> <!-- PHP INI settings and constants definition --> diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/_files/menu/expected.txt b/dev/tests/integration/testsuite/Magento/Backend/Block/_files/menu/expected.txt index fc890c803aae34f8ca74f4c00a541415b426034a..dc07065f7be1e4b2db53584c769bb52abb79de21 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/_files/menu/expected.txt +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/_files/menu/expected.txt @@ -1 +1 @@ -<ul id="nav" role="menubar" ><li data-ui-id="magento-backend-system" class="item-system parent last level-0" id="magento-backend-system" aria-haspopup="true" role="menu-item"><a href="#" onclick="return false;" class=""><span>System</span></a><div class="submenu" aria-labelledby="magento-backend-system"><ul role="menu" ><li data-ui-id="magento-backend-system-report" class="item-system-report parent level-1" role="menu-item"><strong class="submenu-group-title" role="presentation"><span>Report</span></strong><div class="submenu"><ul role="menu" ><li data-ui-id="magento-backend-system-report-private-sales" class="item-system-report-private-sales level-2" role="menu-item"><a href="#" onclick="return false;" class=""><span>Private Sales</span></a></li><li data-ui-id="magento-backend-system-report-magento-invite-general" class="item-system-report-magento-invite-general level-2" role="menu-item"><a href="#" onclick="return false;" class=""><span>Invite</span></a></li><li data-ui-id="magento-backend-system-report-magento-invite-customer" class="item-system-report-magento-invite-customer level-2" role="menu-item"><a href="#" onclick="return false;" class=""><span>Invited Customers</span></a></li></ul></div></li></ul></div></li></ul> \ No newline at end of file +<ul id="nav" role="menubar" ><li data-ui-id="magento-backend-system" class="item-system parent last level-0" id="magento-backend-system" aria-haspopup="true" role="menu-item"><a href="#" onclick="return false;" class=""><span>System</span></a><div class="submenu" aria-labelledby="magento-backend-system"><ul role="menu" ><div class="submenu"><ul role="menu" ><li data-ui-id="magento-backend-system-report-private-sales" class="item-system-report-private-sales level-2" role="menu-item"><a href="#" onclick="return false;" class=""><span>Private Sales</span></a></li><li data-ui-id="magento-backend-system-report-magento-invite-general" class="item-system-report-magento-invite-general level-2" role="menu-item"><a href="#" onclick="return false;" class=""><span>Invite</span></a></li><li data-ui-id="magento-backend-system-report-magento-invite-customer" class="item-system-report-magento-invite-customer level-2" role="menu-item"><a href="#" onclick="return false;" class=""><span>Invited Customers</span></a></li></ul></div></ul></div></li></ul> \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php index 09c21758cba336cbd15982d610875cbc0aa19117..c0cc101fd36bfe94dd5dcc19481d81d14b926132 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Model/Locale/ResolverTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Backend\Model\Locale; +use Magento\Framework\Locale\Resolver; + /** * @magentoAppArea adminhtml */ @@ -28,7 +30,7 @@ class ResolverTest extends \PHPUnit_Framework_TestCase */ public function testSetLocaleWithDefaultLocale() { - $this->_checkSetLocale(\Magento\Framework\Locale\ResolverInterface::DEFAULT_LOCALE); + $this->_checkSetLocale(Resolver::DEFAULT_LOCALE); } /** diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/etc/data_object.xml b/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/service_data_attributes.xml similarity index 63% rename from dev/tests/integration/testsuite/Magento/Customer/_files/etc/data_object.xml rename to dev/tests/integration/testsuite/Magento/Catalog/_files/etc/service_data_attributes.xml index a75fa2a653213ade29aa7ea81e8482e752ed9210..93cf7bfb484a6de773ab318549385ad2436f2fa4 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/_files/etc/data_object.xml +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/service_data_attributes.xml @@ -5,22 +5,22 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> - </custom_attributes> - <custom_attributes for="Magento\Catalog\Api\Data\ProductInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + </extension_attributes> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="stock_item" type="Magento\CatalogInventory\Service\Data\V1\StockItem" /> - </custom_attributes> - <custom_attributes for="Magento\Catalog\Api\Data\CategoryInterface"> + </extension_attributes> + <extension_attributes for="Magento\Catalog\Api\Data\CategoryInterface"> <attribute code="category_attribute_1" type="Magento\Catalog\Api\Data\CategoryAttributeType1" /> <attribute code="category_attribute_2" type="Magento\Catalog\Api\Data\CategoryAttributeType2" /> - </custom_attributes> - <custom_attributes for="Magento\Customer\Api\Data\CustomerInterface"> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> <attribute code="customer_attribute_1" type="Magento\Customer\Api\Data\CustomerAttributeType1" /> <attribute code="customer_attribute_2" type="Magento\Customer\Api\Data\CustomerAttributeType2" /> - </custom_attributes> - <custom_attributes for="Magento\Customer\Api\Data\AddressInterface"> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\Address"> <attribute code="address_attribute_1" type="Magento\Customer\Api\Data\AddressAttributeType1" /> <attribute code="address_attribute_2" type="Magento\Customer\Api\Data\AddressAttributeType2" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php index def5584983e613573b91eeff95d766599b82655a..a83bb8be1c9feec57cb2e722d69021549a786615 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -125,4 +125,50 @@ class ProductTest extends \PHPUnit_Framework_TestCase ); } } + + /** + * Verifies if exception processing works properly + * + * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php + */ + public function testExceptionInGetExportData() + { + $exception = new \Exception('Error'); + + $rowCustomizerMock = $this->getMockBuilder('Magento\CatalogImportExport\Model\Export\RowCustomizerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $loggerMock = $this->getMockBuilder('\Psr\Log\LoggerInterface')->getMock(); + + $directoryMock = $this->getMock('Magento\Framework\Filesystem\Directory\Write', [], [], '', false); + $directoryMock->expects($this->any())->method('getParentDirectory')->will($this->returnValue('some#path')); + $directoryMock->expects($this->any())->method('isWritable')->will($this->returnValue(true)); + + $filesystemMock = $this->getMock('Magento\Framework\Filesystem', [], [], '', false); + $filesystemMock->expects($this->once())->method('getDirectoryWrite')->will($this->returnValue($directoryMock)); + + $exportAdapter = new \Magento\ImportExport\Model\Export\Adapter\Csv($filesystemMock); + + $rowCustomizerMock->expects($this->once())->method('prepareData')->willThrowException($exception); + $loggerMock->expects($this->once())->method('critical')->with($exception); + + $collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + '\Magento\Catalog\Model\Resource\Product\Collection' + ); + + /** @var \Magento\CatalogImportExport\Model\Export\Product $model */ + $model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\CatalogImportExport\Model\Export\Product', + [ + 'rowCustomizer' => $rowCustomizerMock, + 'logger' => $loggerMock, + 'collection' => $collection + ] + ); + + + $data = $model->setWriter($exportAdapter)->export(); + $this->assertEmpty($data); + } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php index 2a99dede484227e4b7bc38fd9040e78573584869..ab40348430e024c0d58e42d8ee649321c0ec754b 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php @@ -79,7 +79,6 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase public function testSetUsedProductAttributeIds() { $testConfigurable = $this->_getAttributeByCode('test_configurable'); - $this->assertEmpty($this->_product->getData('_cache_instance_configurable_attributes')); $this->_model->setUsedProductAttributeIds([$testConfigurable->getId()], $this->_product); $attributes = $this->_product->getData('_cache_instance_configurable_attributes'); $this->assertArrayHasKey(0, $attributes); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..5772edc9317ae5a0a41a9d4aafd419ea982e53fa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry'); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Eav\Model\Config'); +$attribute = $eavConfig->getAttribute('catalog_product', 'test_configurable'); +if ($attribute instanceof \Magento\Eav\Model\Entity\Attribute\AbstractAttribute + && $attribute->getId() +) { + $attribute->delete(); +} +$eavConfig->clear(); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php index b083d7e52dfb293b687d837f145b54909240e617..cc615bf03ea85243af323bf7844bc3d33acac7c9 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php @@ -12,17 +12,16 @@ $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create ['resourceName' => 'catalog_setup'] ); -/* Create simple products per each option */ -/** @var $options \Magento\Eav\Model\Resource\Entity\Attribute\Option\Collection */ -$options = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - 'Magento\Eav\Model\Resource\Entity\Attribute\Option\Collection' -); -$options->setAttributeFilter($attribute->getId()); +/* Create simple products per each option value*/ + +/** @var \Magento\Eav\Api\Data\AttributeOptionInterface[] $options */ +$options = $attribute->getOptions(); $attributeValues = []; $productIds = []; $attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default'); $productIds = [10, 20]; +array_shift($options); //remove the first option which is empty foreach ($options as $option) { /** @var $product \Magento\Catalog\Model\Product */ $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product'); @@ -36,13 +35,13 @@ foreach ($options as $option) { )->setWebsiteIds( [1] )->setName( - 'Configurable Option' . $option->getId() + 'Configurable Option' . $option->getLabel() )->setSku( 'simple_' . $productId )->setPrice( 10 )->setTestConfigurable( - $option->getId() + $option->getValue() )->setVisibility( \Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE )->setStatus( @@ -54,7 +53,7 @@ foreach ($options as $option) { $attributeValues[] = [ 'label' => 'test', 'attribute_id' => $attribute->getId(), - 'value_index' => $option->getId(), + 'value_index' => $option->getValue(), 'is_percent' => false, 'pricing_value' => 5, ]; diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_rollback.php index c1b23ce233c9e09240533d5bc7ee97f90a7510da..f1e17b724c8b476f76a622837d2120b0df1c96cd 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_rollback.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_rollback.php @@ -26,6 +26,11 @@ $product->load(1); if ($product->getId()) { $product->delete(); } +\Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get('Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Price\Data') + ->setProductPrice(1, null); + +require __DIR__ . '/configurable_attribute_rollback.php'; $registry->unregister('isSecureArea'); $registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php index b3c578e46cfa26069c1c93c07ac1b15bc3ea59e7..da3a723a0db759702ecd505510159f614a9b5105 100755 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php @@ -102,7 +102,7 @@ class IndexTest extends \Magento\Backend\Utility\Controller public function testSaveActionWithInvalidCustomerAddressData() { $post = [ - 'account' => [ + 'customer' => [ 'middlename' => 'test middlename', 'group_id' => 1, 'website_id' => 0, @@ -110,8 +110,8 @@ class IndexTest extends \Magento\Backend\Utility\Controller 'lastname' => 'test lastname', 'email' => 'example@domain.com', 'default_billing' => '_item1', - 'customer_address' => ['_item1' => []], ], + 'address' => ['_item1' => []], ]; $this->getRequest()->setPostValue($post); $this->dispatch('backend/customer/index/save'); @@ -141,7 +141,7 @@ class IndexTest extends \Magento\Backend\Utility\Controller $objectManager = Bootstrap::getObjectManager(); $post = [ - 'account' => [ + 'customer' => [ 'middlename' => 'test middlename', 'group_id' => 1, 'website_id' => 0, @@ -150,17 +150,17 @@ class IndexTest extends \Magento\Backend\Utility\Controller 'email' => 'example@domain.com', 'default_billing' => '_item1', 'password' => 'password', - 'customer_address' => [ - '_item1' => [ - 'firstname' => 'test firstname', - 'lastname' => 'test lastname', - 'street' => ['test street'], - 'city' => 'test city', - 'country_id' => 'US', - 'postcode' => '01001', - 'telephone' => '+7000000001', - 'default_billing' => 'true', - ], + ], + 'address' => [ + '_item1' => [ + 'firstname' => 'test firstname', + 'lastname' => 'test lastname', + 'street' => ['test street'], + 'city' => 'test city', + 'country_id' => 'US', + 'postcode' => '01001', + 'telephone' => '+7000000001', + 'default_billing' => 'true', ], ], ]; @@ -218,8 +218,8 @@ class IndexTest extends \Magento\Backend\Utility\Controller public function testSaveActionExistingCustomerAndExistingAddressData() { $post = [ - 'customer_id' => '1', - 'account' => [ + 'customer' => [ + 'entity_id' => '1', 'middlename' => 'test middlename', 'group_id' => 1, 'website_id' => 1, @@ -232,39 +232,38 @@ class IndexTest extends \Magento\Backend\Utility\Controller 'created_at' => '2000-01-01 00:00:00', 'default_shipping' => '_item1', 'default_billing' => 1, - 'customer_address' => [ - '1' => [ - 'firstname' => 'update firstname', - 'lastname' => 'update lastname', - 'street' => ['update street'], - 'city' => 'update city', - 'country_id' => 'US', - 'postcode' => '01001', - 'telephone' => '+7000000001', - 'default_billing' => 'true', - ], - '_item1' => [ - 'firstname' => 'new firstname', - 'lastname' => 'new lastname', - 'street' => ['new street'], - 'city' => 'new city', - 'country_id' => 'US', - 'postcode' => '01001', - 'telephone' => '+7000000001', - 'default_shipping' => 'true', - ], - '_template_' => [ - 'firstname' => '', - 'lastname' => '', - 'street' => [], - 'city' => '', - 'country_id' => 'US', - 'postcode' => '', - 'telephone' => '', - ], + ], + 'address' => [ + '1' => [ + 'firstname' => 'update firstname', + 'lastname' => 'update lastname', + 'street' => ['update street'], + 'city' => 'update city', + 'country_id' => 'US', + 'postcode' => '01001', + 'telephone' => '+7000000001', + 'default_billing' => 'true', + ], + '_item1' => [ + 'firstname' => 'new firstname', + 'lastname' => 'new lastname', + 'street' => ['new street'], + 'city' => 'new city', + 'country_id' => 'US', + 'postcode' => '01001', + 'telephone' => '+7000000001', + 'default_shipping' => 'true', + ], + '_template_' => [ + 'firstname' => '', + 'lastname' => '', + 'street' => [], + 'city' => '', + 'country_id' => 'US', + 'postcode' => '', + 'telephone' => '', ], ], - 'subscription' => '', ]; $this->getRequest()->setPostValue($post); @@ -330,7 +329,7 @@ class IndexTest extends \Magento\Backend\Utility\Controller $this->assertEquals(1, $subscriber->getStatus()); $post = [ - 'customer_id' => $customerId, + 'customer' => ['entity_id' => $customerId], ]; $this->getRequest()->setPostValue($post); $this->getRequest()->setParam('id', 1); @@ -360,7 +359,7 @@ class IndexTest extends \Magento\Backend\Utility\Controller public function testSaveActionCoreException() { $post = [ - 'account' => [ + 'customer' => [ 'middlename' => 'test middlename', 'group_id' => 1, 'website_id' => 1, @@ -477,7 +476,7 @@ class IndexTest extends \Magento\Backend\Utility\Controller { $customerData = [ 'customer_id' => 0, - 'account' => [ + 'customer' => [ 'created_in' => false, 'disable_auto_group_change' => false, 'email' => false, @@ -887,8 +886,8 @@ class IndexTest extends \Magento\Backend\Utility\Controller public function testValidateCustomerWithAddressSuccess() { $customerData = [ - 'id' => '1', - 'account' => [ + 'customer' => [ + 'entity_id' => '1', 'middlename' => 'new middlename', 'group_id' => 1, 'website_id' => 1, @@ -943,8 +942,8 @@ class IndexTest extends \Magento\Backend\Utility\Controller public function testValidateCustomerWithAddressFailure() { $customerData = [ - 'id' => '1', - 'account' => [ + 'customer' => [ + 'entity_id' => '1', 'middlename' => 'new middlename', 'group_id' => 1, 'website_id' => 1, @@ -955,30 +954,30 @@ class IndexTest extends \Magento\Backend\Utility\Controller 'new_password' => 'auto', 'sendemail_store_id' => '1', 'sendemail' => '1', - 'customer_address' => [ - '1' => [ - 'firstname' => '', - 'lastname' => '', - 'street' => ['update street'], - 'city' => 'update city', - 'postcode' => '01001', - 'telephone' => '', - ], - '_template_' => [ - 'lastname' => '', - 'street' => [], - 'city' => '', - 'country_id' => 'US', - 'postcode' => '', - 'telephone' => '', - ], + ], + 'address' => [ + '1' => [ + 'firstname' => '', + 'lastname' => '', + 'street' => ['update street'], + 'city' => 'update city', + 'postcode' => '01001', + 'telephone' => '', + ], + '_template_' => [ + 'lastname' => '', + 'street' => [], + 'city' => '', + 'country_id' => 'US', + 'postcode' => '', + 'telephone' => '', ], ], ]; /** * set customer data */ - $this->getRequest()->setParams($customerData); + $this->getRequest()->setPostValue($customerData); $this->dispatch('backend/customer/index/validate'); $body = $this->getResponse()->getBody(); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php b/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php index 48d81d30eb84119c45e440be2e57bd48b4c3c8e9..9ee9ed911f7c092aac6034ed441e5c96f2e46aa2 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php @@ -21,7 +21,7 @@ class FileResolverStub implements \Magento\Framework\Config\FileResolverInterfac 'path' => realpath(__DIR__ . '/../_files/etc'), ] ); - $paths = ['data_object.xml']; + $paths = ['service_data_attributes.xml']; return new \Magento\Framework\Config\FileIterator($readDirectory, $paths); } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/data_object.xml b/dev/tests/integration/testsuite/Magento/Customer/_files/etc/service_data_attributes.xml similarity index 63% rename from dev/tests/integration/testsuite/Magento/Catalog/_files/etc/data_object.xml rename to dev/tests/integration/testsuite/Magento/Customer/_files/etc/service_data_attributes.xml index c2888a64ee00c0e6f18a7d1126920e4c85a8b091..a7ae041eda7683ce99dd168befc50c2ae5a46f3c 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/data_object.xml +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/etc/service_data_attributes.xml @@ -5,22 +5,22 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> - </custom_attributes> - <custom_attributes for="Magento\Catalog\Api\Data\ProductInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + </extension_attributes> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="stock_item" type="Magento\CatalogInventory\Service\Data\V1\StockItem" /> - </custom_attributes> - <custom_attributes for="Magento\Catalog\Api\Data\CategoryInterface"> + </extension_attributes> + <extension_attributes for="Magento\Catalog\Api\Data\CategoryInterface"> <attribute code="category_attribute_1" type="Magento\Catalog\Api\Data\CategoryAttributeType1" /> <attribute code="category_attribute_2" type="Magento\Catalog\Api\Data\CategoryAttributeType2" /> - </custom_attributes> - <custom_attributes for="Magento\Customer\Api\Data\CustomerInterface"> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> <attribute code="customer_attribute_1" type="Magento\Customer\Api\Data\CustomerAttributeType1" /> <attribute code="customer_attribute_2" type="Magento\Customer\Api\Data\CustomerAttributeType2" /> - </custom_attributes> - <custom_attributes for="Magento\Customer\Api\Data\Address"> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\AddressInterface"> <attribute code="address_attribute_1" type="Magento\Customer\Api\Data\AddressAttributeType1" /> <attribute code="address_attribute_2" type="Magento\Customer\Api\Data\AddressAttributeType2" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/dev/tests/integration/testsuite/Magento/DatabaseTest.php b/dev/tests/integration/testsuite/Magento/DatabaseTest.php index 4058fcb2b444abeac044b35cd4e368fb6006b238..77e767b03f9a2700d318e05fd1dbcb348d393315 100644 --- a/dev/tests/integration/testsuite/Magento/DatabaseTest.php +++ b/dev/tests/integration/testsuite/Magento/DatabaseTest.php @@ -21,7 +21,7 @@ class DatabaseTest extends \PHPUnit_Framework_TestCase $db = Bootstrap::getInstance()->getBootstrap()->getApplication()->getDbInstance(); $command = $checkerPath . ' -d ' . $db->getSchema() - . ' h=' . $db->getHost()['db_host'] . ',u=' . $db->getUser() . ',p=' . $db->getPassword(); + . ' h=' . $db->getHost()['db-host'] . ',u=' . $db->getUser() . ',p=' . $db->getPassword(); exec($command, $output, $exitCode); $this->assertEquals(0, $exitCode); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/ReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/Api/Config/ReaderTest.php index 351a0ba03144a218481d9ab798cca18989ca8db8..07fceddb6424b3bc01d7e4448833cb92a709d6c9 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/ReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/Config/ReaderTest.php @@ -76,12 +76,24 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $expectedArray = [ 'Magento\Tax\Api\Data\TaxRateInterface' => [], 'Magento\Catalog\Api\Data\Product' => [ - 'stock_item' => "Magento\CatalogInventory\Api\Data\StockItem", + 'stock_item' => [ + "type" => "Magento\CatalogInventory\Api\Data\StockItem", + "resourceRefs" => [], + ], ], 'Magento\Customer\Api\Data\CustomerInterface' => [ - 'custom_1' => "Magento\Customer\Api\Data\CustomerCustom", - 'custom_2' => "Magento\CustomerExtra\Api\Data\CustomerCustom22", - 'custom_3' => "Magento\Customer\Api\Data\CustomerCustom3", + 'custom_1' => [ + "type" => "Magento\Customer\Api\Data\CustomerCustom", + "resourceRefs" => [], + ], + 'custom_2' => [ + "type" => "Magento\CustomerExtra\Api\Data\CustomerCustom22", + "resourceRefs" => [], + ], + 'custom_3' => [ + "type" => "Magento\Customer\Api\Data\CustomerCustom3", + "resourceRefs" => [], + ], ], ]; diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_one.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_one.xml index f5a3d522454ab487f461f697e6108f118f1769e9..82aa641d5e8bd9040d9fa26689d95a09b74e19f3 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_one.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_one.xml @@ -5,14 +5,14 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> - </custom_attributes> - <custom_attributes for="Magento\Catalog\Api\Data\Product"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + </extension_attributes> + <extension_attributes for="Magento\Catalog\Api\Data\Product"> <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItem" /> - </custom_attributes> - <custom_attributes for="Magento\Customer\Api\Data\CustomerInterface"> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom" /> <attribute code="custom_2" type="Magento\CustomerExtra\Service\V1\Data\CustomerCustom21" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_two.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_two.xml index 629efb9b7a30a400dad479894f71d0711da8f24d..5596f61e572f4b076a1d850b38002b6a448a7297 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_two.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_two.xml @@ -5,9 +5,9 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Customer\Api\Data\CustomerInterface"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> <attribute code="custom_2" type="Magento\CustomerExtra\Api\Data\CustomerCustom22" /> <attribute code="custom_3" type="Magento\Customer\Api\Data\CustomerCustom3" /> - </custom_attributes> + </extension_attributes> </config> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Session/SessionManagerTest.php b/dev/tests/integration/testsuite/Magento/Framework/Session/SessionManagerTest.php index c8379e5e9c39f37bb5d4edd46ed4720aa250b788..18a4314710c3d9a19f51bf5688afcc7087b90f93 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Session/SessionManagerTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Session/SessionManagerTest.php @@ -3,153 +3,214 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Session; - -class SessionManagerTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Framework\Session\SessionManagerInterface - */ - protected $_model; - - /** - * @var \Magento\Framework\Session\SidResolverInterface - */ - protected $_sidResolver; - - /** - * @var string - */ - protected $sessionName; - - /** - * @var \Magento\Framework\App\RequestInterface - */ - protected $request; - - protected function setUp() - { - $this->sessionName = 'frontEndSession'; - - ini_set('session.use_only_cookies', '0'); - ini_set('session.name', $this->sessionName); - - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - /** @var \Magento\Framework\Session\SidResolverInterface $sidResolver */ - $this->_sidResolver = $objectManager->get('Magento\Framework\Session\SidResolverInterface'); - - $this->request = $objectManager->get('Magento\Framework\App\RequestInterface'); - - /** @var \Magento\Framework\Session\SessionManager _model */ - $this->_model = $objectManager->create( - 'Magento\Framework\Session\SessionManager', - [ - $this->request, - $this->_sidResolver, - $objectManager->get('Magento\Framework\Session\Config\ConfigInterface'), - $objectManager->get('Magento\Framework\Session\SaveHandlerInterface'), - $objectManager->get('Magento\Framework\Session\ValidatorInterface'), - $objectManager->get('Magento\Framework\Session\StorageInterface') - ] - ); - } - - public function testSessionNameFromIni() - { - $this->_model->start(); - $this->assertSame($this->sessionName, $this->_model->getName()); - $this->_model->destroy(); - } - - public function testSessionUseOnlyCookies() - { - $expectedValue = '1'; - $sessionUseOnlyCookies = ini_get('session.use_only_cookies'); - $this->assertSame($expectedValue, $sessionUseOnlyCookies); - } - - public function testGetData() - { - $this->_model->setData(['test_key' => 'test_value']); - $this->assertEquals('test_value', $this->_model->getData('test_key', true)); - $this->assertNull($this->_model->getData('test_key')); - } - - public function testGetSessionId() - { - $this->assertEquals(session_id(), $this->_model->getSessionId()); - } - - public function testGetName() - { - $this->assertEquals(session_name(), $this->_model->getName()); - } - - public function testSetName() - { - $this->_model->setName('test'); - $this->assertEquals('test', $this->_model->getName()); - } - - public function testDestroy() - { - $data = ['key' => 'value']; - $this->_model->setData($data); - - $this->assertEquals($data, $this->_model->getData()); - $this->_model->destroy(); - - $this->assertEquals([], $this->_model->getData()); - } +// @codingStandardsIgnoreStart +namespace { + $mockPHPFunctions = false; +} - public function testSetSessionId() - { - $sessionId = $this->_model->getSessionId(); - $this->_model->setSessionId($this->_sidResolver->getSid($this->_model)); - $this->assertEquals($sessionId, $this->_model->getSessionId()); - - $this->_model->setSessionId('test'); - $this->assertEquals('test', $this->_model->getSessionId()); - } +namespace Magento\Framework\Session { + // @codingStandardsIgnoreEnd /** - * @magentoConfigFixture current_store web/session/use_frontend_sid 1 + * Mock session_status if in test mode, or continue normal execution otherwise + * + * @return int Session status code */ - public function testSetSessionIdFromParam() + function session_status() { - $this->assertNotEquals('test_id', $this->_model->getSessionId()); - $this->request->getQuery()->set($this->_sidResolver->getSessionIdQueryParam($this->_model), 'test-id'); - $this->_model->setSessionId($this->_sidResolver->getSid($this->_model)); - - $this->assertEquals('test-id', $this->_model->getSessionId()); - - /* Use not valid identifier */ - $this->request->getQuery()->set($this->_sidResolver->getSessionIdQueryParam($this->_model), 'test_id'); - $this->_model->setSessionId($this->_sidResolver->getSid($this->_model)); - $this->assertEquals('test-id', $this->_model->getSessionId()); + global $mockPHPFunctions; + if ($mockPHPFunctions) { + return PHP_SESSION_NONE; + } + return call_user_func_array('\session_status', func_get_args()); } - public function testGetSessionIdForHost() + function headers_sent() { - $this->request->getServer()->set('HTTP_HOST', 'localhost'); - $this->_model->start(); - $this->assertEmpty($this->_model->getSessionIdForHost('localhost')); - $this->assertNotEmpty($this->_model->getSessionIdForHost('test')); - $this->_model->destroy(); + global $mockPHPFunctions; + if ($mockPHPFunctions) { + return false; + } + return call_user_func_array('\headers_sent', func_get_args()); } - public function testIsValidForHost() + class SessionManagerTest extends \PHPUnit_Framework_TestCase { - $this->request->getServer()->set('HTTP_HOST', 'localhost'); - $this->_model->start(); - - $reflection = new \ReflectionMethod($this->_model, '_addHost'); - $reflection->setAccessible(true); - $reflection->invoke($this->_model); - - $this->assertFalse($this->_model->isValidForHost('test.com')); - $this->assertTrue($this->_model->isValidForHost('localhost')); - $this->_model->destroy(); + /** + * @var \Magento\Framework\Session\SessionManagerInterface + */ + protected $_model; + + /** + * @var \Magento\Framework\Session\SidResolverInterface + */ + protected $_sidResolver; + + /** + * @var string + */ + protected $sessionName; + + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $objectManager; + + protected function setUp() + { + $this->sessionName = 'frontEndSession'; + + ini_set('session.use_only_cookies', '0'); + ini_set('session.name', $this->sessionName); + + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + /** @var \Magento\Framework\Session\SidResolverInterface $sidResolver */ + $this->_sidResolver = $this->objectManager->get('Magento\Framework\Session\SidResolverInterface'); + + $this->request = $this->objectManager->get('Magento\Framework\App\RequestInterface'); + + /** @var \Magento\Framework\Session\SessionManager _model */ + $this->_model = $this->objectManager->create( + 'Magento\Framework\Session\SessionManager', + [ + $this->objectManager->get('Magento\Framework\App\Request\Http'), + $this->_sidResolver, + $this->objectManager->get('Magento\Framework\Session\Config\ConfigInterface'), + $this->objectManager->get('Magento\Framework\Session\SaveHandlerInterface'), + $this->objectManager->get('Magento\Framework\Session\ValidatorInterface'), + $this->objectManager->get('Magento\Framework\Session\StorageInterface') + ] + ); + } + + public function testSessionNameFromIni() + { + $this->_model->start(); + $this->assertSame($this->sessionName, $this->_model->getName()); + $this->_model->destroy(); + } + + public function testSessionUseOnlyCookies() + { + $expectedValue = '1'; + $sessionUseOnlyCookies = ini_get('session.use_only_cookies'); + $this->assertSame($expectedValue, $sessionUseOnlyCookies); + } + + public function testGetData() + { + $this->_model->setData(['test_key' => 'test_value']); + $this->assertEquals('test_value', $this->_model->getData('test_key', true)); + $this->assertNull($this->_model->getData('test_key')); + } + + public function testGetSessionId() + { + $this->assertEquals(session_id(), $this->_model->getSessionId()); + } + + public function testGetName() + { + $this->assertEquals(session_name(), $this->_model->getName()); + } + + public function testSetName() + { + $this->_model->setName('test'); + $this->assertEquals('test', $this->_model->getName()); + } + + public function testDestroy() + { + $data = ['key' => 'value']; + $this->_model->setData($data); + + $this->assertEquals($data, $this->_model->getData()); + $this->_model->destroy(); + + $this->assertEquals([], $this->_model->getData()); + } + + public function testSetSessionId() + { + $sessionId = $this->_model->getSessionId(); + $this->_model->setSessionId($this->_sidResolver->getSid($this->_model)); + $this->assertEquals($sessionId, $this->_model->getSessionId()); + + $this->_model->setSessionId('test'); + $this->assertEquals('test', $this->_model->getSessionId()); + } + + /** + * @magentoConfigFixture current_store web/session/use_frontend_sid 1 + */ + public function testSetSessionIdFromParam() + { + $this->assertNotEquals('test_id', $this->_model->getSessionId()); + $this->request->getQuery()->set($this->_sidResolver->getSessionIdQueryParam($this->_model), 'test-id'); + $this->_model->setSessionId($this->_sidResolver->getSid($this->_model)); + $this->assertEquals('test-id', $this->_model->getSessionId()); + /* Use not valid identifier */ + $this->request->getQuery()->set($this->_sidResolver->getSessionIdQueryParam($this->_model), 'test_id'); + $this->_model->setSessionId($this->_sidResolver->getSid($this->_model)); + $this->assertEquals('test-id', $this->_model->getSessionId()); + } + + public function testGetSessionIdForHost() + { + $_SERVER['HTTP_HOST'] = 'localhost'; + $this->_model->start(); + $this->assertEmpty($this->_model->getSessionIdForHost('localhost')); + $this->assertNotEmpty($this->_model->getSessionIdForHost('test')); + $this->_model->destroy(); + } + + public function testIsValidForHost() + { + $_SERVER['HTTP_HOST'] = 'localhost'; + $this->_model->start(); + + $reflection = new \ReflectionMethod($this->_model, '_addHost'); + $reflection->setAccessible(true); + $reflection->invoke($this->_model); + + $this->assertFalse($this->_model->isValidForHost('test.com')); + $this->assertTrue($this->_model->isValidForHost('localhost')); + $this->_model->destroy(); + } + + + /** + * @expectedException \Magento\Framework\Exception\SessionException + * @expectedExceptionMessage Area code not set: Area code must be set before starting a session. + */ + public function testStartAreaNotSet() + { + $scope = $this->objectManager->get('Magento\Framework\Config\ScopeInterface'); + $appState = new \Magento\Framework\App\State($scope); + + /** + * Must be created by "new" in order to get a real Magento\Framework\App\State object that + * is not overridden in the TestFramework + * + * @var \Magento\Framework\Session\SessionManager _model + */ + $this->_model = new \Magento\Framework\Session\SessionManager( + $this->objectManager->get('Magento\Framework\App\Request\Http'), + $this->_sidResolver, + $this->objectManager->get('Magento\Framework\Session\Config\ConfigInterface'), + $this->objectManager->get('Magento\Framework\Session\SaveHandlerInterface'), + $this->objectManager->get('Magento\Framework\Session\ValidatorInterface'), + $this->objectManager->get('Magento\Framework\Session\StorageInterface'), + $this->objectManager->get('Magento\Framework\Stdlib\CookieManagerInterface'), + $this->objectManager->get('Magento\Framework\Stdlib\Cookie\CookieMetadataFactory'), + $appState + ); + + global $mockPHPFunctions; + $mockPHPFunctions = true; + $this->_model->start(); + } } } diff --git a/dev/tests/integration/testsuite/Magento/Payment/Block/Transparent/IframeTest.php b/dev/tests/integration/testsuite/Magento/Payment/Block/Transparent/IframeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c91ead38e49e959564d03b2f90785d4f5e710bdb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Payment/Block/Transparent/IframeTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Block\Transparent; + +class IframeTest extends \PHPUnit_Framework_TestCase +{ + /** + * @magentoAppIsolation enabled + * @magentoAppArea frontend + */ + public function testToHtml() + { + $xssString = '</script><script>alert("XSS")</script>'; + + /** @var $block Iframe */ + $block = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + 'Magento\Framework\View\LayoutInterface' + )->createBlock( + 'Magento\Payment\Block\Transparent\Iframe' + ); + + $block->setTemplate('transparent/iframe.phtml'); + $block->setData( + 'params', + [ + 'redirect' => $xssString, + 'redirect_parent' => $xssString, + 'error_msg' => $xssString + ] + ); + + $content = $block->toHtml(); + + $this->assertNotContains($xssString, $content, 'Params mast be escaped'); + $this->assertContains(htmlspecialchars($xssString), $content, 'Content must present'); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Payment/Model/ObserverTest.php b/dev/tests/integration/testsuite/Magento/Payment/Model/ObserverTest.php index 14f306766a10720ac021fc9ce9b94ecff8ee08cd..f83337a307eb201a8d5fd2fc8ef9dc8d6005880a 100644 --- a/dev/tests/integration/testsuite/Magento/Payment/Model/ObserverTest.php +++ b/dev/tests/integration/testsuite/Magento/Payment/Model/ObserverTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Payment\Model; +use Magento\Framework\App\Config\ScopeConfigInterface; + /** * @magentoAppArea adminhtml */ @@ -68,7 +70,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase $config->saveConfig( 'payment/checkmo/order_status', $statusCode, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0 ); diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php index 1313db5e278a098d9687b95ed80501862295b0ec..0a35f0488948b5d142693ee2a423f600eab01e7b 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php @@ -7,6 +7,7 @@ namespace Magento\Sales\Controller\Adminhtml\Order; /** * @magentoAppArea adminhtml + * @magentoDbIsolation enabled */ class CreateTest extends \Magento\Backend\Utility\Controller { diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index 8fbdd0f346d4b0c410bd35387dd45564504b61f8..a84b46c3c2981e420d24a251db6a0b46cc332eee 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -451,7 +451,8 @@ class StoreTest extends \PHPUnit_Framework_TestCase [true, ['HTTPS' => 'on']], [true, ['SSL_OFFLOADED' => 'https']], [true, ['HTTP_SSL_OFFLOADED' => 'https']], - [true, ['SERVER_PORT' => 80]], + [true, ['HTTPS' => 'on', 'SERVER_PORT' => 80]], + [false, ['SERVER_PORT' => 80]], [false, []], ]; } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Block/Adminhtml/Rate/FormTest.php b/dev/tests/integration/testsuite/Magento/Tax/Block/Adminhtml/Rate/FormTest.php deleted file mode 100644 index 0bc80a86389f29b09fc9d4b80b001347662d97f8..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/Tax/Block/Adminhtml/Rate/FormTest.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Tax\Block\Adminhtml\Rate; - -use Magento\TestFramework\Helper\Bootstrap; - -class FormTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $_objectManager; - - /** @var \Magento\Tax\Block\Adminhtml\Rate\Form */ - protected $_block; - - protected function setUp() - { - $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->_block = $this->_objectManager->create( - 'Magento\Tax\Block\Adminhtml\Rate\Form' - ); - } - - public function testGetRateCollection() - { - /** @var \Magento\Tax\Model\Resource\Calculation\Rate\Collection $collection */ - $collection = Bootstrap::getObjectManager()->get('Magento\Tax\Model\Resource\Calculation\Rate\Collection'); - $dbTaxRatesQty = $collection->count(); - if (($dbTaxRatesQty == 0) || ($collection->getFirstItem()->getId() != 1)) { - $this->fail("Preconditions failed."); - } - - $ratesCollection = $this->_block->getRateCollection(); - - $collectionTaxRatesQty = count($ratesCollection); - $this->assertEquals($dbTaxRatesQty, $collectionTaxRatesQty, 'Tax rates quantity is invalid.'); - $taxRate = $ratesCollection[0]; - $expectedTaxRateData = [ - 'tax_calculation_rate_id' => '1', - 'code' => 'US-CA-*-Rate 1', - 'tax_country_id' => 'US', - 'tax_region_id' => '12', - 'region_name' => 'CA', - 'tax_postcode' => '*', - 'rate' => '8.25', - 'zip_is_range' => null, - 'zip_from' => null, - 'zip_to' => null, - 'rate' => '8.25', - ]; - $this->assertEquals($taxRate, $expectedTaxRateData, 'Tax rate data is invalid.'); - } -} diff --git a/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php b/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php index b6e6a11859231e98d4f303fcec041ff6f690ad38..ab5c6cd2ba0d57b05bd90e250dd4550a254010e1 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php @@ -44,6 +44,11 @@ class RateTest extends \Magento\Backend\Utility\Controller $this->assertEquals($expectedData['tax_postcode'], $rate->getTaxPostcode()); } + /** + * Data provider for testAjaxSaveAction + * + * @return array + */ public function ajaxSaveActionDataProvider() { $postData = ['rate' => '10', 'tax_country_id' => 'US', 'tax_region_id' => '1']; @@ -193,4 +198,102 @@ class RateTest extends \Magento\Backend\Utility\Controller ] ]; } + + /** + * @dataProvider ajaxSaveActionDataProvider + * @magentoDbIsolation enabled + * + * @param array $rateClassData + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function testAjaxLoadAction($rateClassData) + { + /** @var \Magento\Tax\Api\Data\TaxRateInterfaceFactory $rateClassFactory */ + $rateClassFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + 'Magento\Tax\Api\Data\TaxRateInterfaceFactory' + ); + + $rateClass = $rateClassFactory->create(); + $rateClass->setRate($rateClassData['rate']) + ->setTaxCountryId($rateClassData['tax_country_id']) + ->setTaxRegionId($rateClassData['tax_region_id']) + ->setCode($rateClassData['code']) + ->setZipFrom($rateClassData['zip_from']) + ->setZipIsRange($rateClassData['zip_is_range']) + ->setZipFrom($rateClassData['zip_from']) + ->setZipTo($rateClassData['zip_to']) + ->setTaxPostcode($rateClassData['tax_postcode']); + + $rateClass->save($rateClass); + + $rateClassId=$rateClass->getTaxCalculationRateId(); + /** @var $class \Magento\Tax\Model\Calculation\Rate */ + $class = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create('Magento\Tax\Model\Calculation\Rate') + ->load($rateClassId, 'tax_calculation_rate_id'); + + $this->assertEquals($rateClassData['tax_country_id'], $class->getTaxCountryId()); + $this->assertEquals($rateClassData['tax_region_id'], $class->getTaxRegionId()); + $this->assertEquals($rateClassData['code'], $class->getCode()); + $this->assertEquals($rateClassData['rate'], $class->getRate()); + $this->assertEquals($rateClassData['zip_is_range']==1 ? 1 : 0, $class->getZipIsRange() ? 1 : 0); + if ($rateClassData['zip_is_range']=='1') { + $this->assertEquals($rateClassData['zip_from'], $class->getZipFrom()); + $this->assertEquals($rateClassData['zip_to'], $class->getZipTo()); + } + + $postData = [ 'id' => $rateClassId ]; + $this->getRequest()->setPostValue($postData); + $this->dispatch('backend/tax/rate/ajaxLoad'); + $jsonBody = $this->getResponse()->getBody(); + + $result = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + 'Magento\Framework\Json\Helper\Data' + )->jsonDecode( + $jsonBody + ); + + $this->assertTrue(is_array($result)); + $this->assertArrayHasKey('success', $result); + $this->assertTrue($result['success'] == true); + $this->assertArrayHasKey('result', $result); + $this->assertTrue(is_array($result['result'])); + $this->assertEquals($result['result']['tax_country_id'], $class->getTaxCountryId()); + $this->assertEquals($result['result']['tax_region_id'], $class->getTaxRegionId()); + $this->assertEquals($result['result']['tax_postcode'], $class->getTaxPostcode()); + $this->assertEquals($result['result']['code'], $class->getCode()); + $this->assertEquals($result['result']['rate'], $class->getRate()); + + $expectedZipIsRange=$result['result']['zip_is_range'] == 1 ? 1 : 0; + $this->assertEquals($expectedZipIsRange, $class->getZipIsRange() ? 1 : 0); + if ($expectedZipIsRange) { + $this->assertEquals($result['result']['zip_from'], $class->getZipFrom()); + $this->assertEquals($result['result']['zip_to'], $class->getZipTo()); + } + } + + /** + * @magentoDbIsolation enabled + * + */ + public function testAjaxNonLoadAction() + { + $postData = [ 'id' => 99999999 ]; + $this->getRequest()->setPostValue($postData); + $this->dispatch('backend/tax/rate/ajaxLoad'); + $jsonBody = $this->getResponse()->getBody(); + + $result = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + 'Magento\Framework\Json\Helper\Data' + )->jsonDecode( + $jsonBody + ); + + $this->assertTrue(is_array($result)); + $this->assertArrayHasKey('success', $result); + $this->assertTrue($result['success'] == false); + $this->assertTrue(!array_key_exists('result', $result)); + $this->assertArrayHasKey('error_message', $result); + $this->assertTrue(strlen($result['error_message'])>0); + } } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php index 1e9c43ca7fd49621116be74791c4a180c2c4763d..2b0d311757846900c2a9b1f9ccffb29cd221d4c1 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/RateRepositoryTest.php @@ -9,6 +9,7 @@ namespace Magento\Tax\Model\Calculation; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Tax\Api\Data\TaxRateInterface; +use Magento\Tax\Model\Calculation\Rate; use Magento\Tax\Model\TaxRuleFixtureFactory; use Magento\TestFramework\Helper\Bootstrap; @@ -566,14 +567,14 @@ class RateRepositoryTest extends \PHPUnit_Framework_TestCase return [ 'eq' => [ - [$filterBuilder->setField(TaxRateInterface::KEY_REGION_ID)->setValue(42)->create()], + [$filterBuilder->setField(Rate::KEY_REGION_ID)->setValue(42)->create()], null, ['US - 42 - 7.5', 'US - 42 - 22'], ], 'and' => [ [ - $filterBuilder->setField(TaxRateInterface::KEY_REGION_ID)->setValue(42)->create(), - $filterBuilder->setField(TaxRateInterface::KEY_PERCENTAGE_RATE)->setValue(22.0)->create(), + $filterBuilder->setField(Rate::KEY_REGION_ID)->setValue(42)->create(), + $filterBuilder->setField(Rate::KEY_PERCENTAGE_RATE)->setValue(22.0)->create(), ], [], ['US - 42 - 22'], @@ -581,15 +582,14 @@ class RateRepositoryTest extends \PHPUnit_Framework_TestCase 'or' => [ [], [ - $filterBuilder->setField(TaxRateInterface::KEY_PERCENTAGE_RATE)->setValue(22.0)->create(), - $filterBuilder->setField(TaxRateInterface::KEY_PERCENTAGE_RATE)->setValue(10.0)->create(), + $filterBuilder->setField(Rate::KEY_PERCENTAGE_RATE)->setValue(22.0)->create(), + $filterBuilder->setField(Rate::KEY_PERCENTAGE_RATE)->setValue(10.0)->create(), ], ['US - 42 - 22', 'US - 12 - 10'], ], 'like' => [ [ - $filterBuilder->setField(TaxRateInterface::KEY_CODE)->setValue('%7.5')->setConditionType('like') - ->create(), + $filterBuilder->setField(Rate::KEY_CODE)->setValue('%7.5')->setConditionType('like')->create(), ], [], ['US - 42 - 7.5', 'US - 12 - 7.5'], diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php index 861079efbac7df145af34557037fa6b79bb886e0..331bfebab31ad4078259e912e982010cb44302e6 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php @@ -8,6 +8,7 @@ namespace Magento\Tax\Model\Sales\Total\Quote; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Tax\Model\Config; use Magento\Tax\Model\Calculation; @@ -221,7 +222,7 @@ class SetupUtil $config->saveConfig( $path, $value, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0 ); } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxCalculationTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxCalculationTest.php index 0c3af306bdeaa8f70d4a0b9e3e0d4bda252693e1..4f8e5da64ba2d3f77397905e9a470127626a84a6 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxCalculationTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxCalculationTest.php @@ -5,8 +5,8 @@ */ namespace Magento\Tax\Model; -use Magento\Framework\Model\AbstractExtensibleModel; use Magento\Tax\Api\Data\TaxClassKeyInterface; +use Magento\Tax\Model\TaxClass\Key; use Magento\TestFramework\Helper\Bootstrap; /** @@ -121,8 +121,8 @@ class TaxCalculationTest extends \PHPUnit_Framework_TestCase 'quantity' => 2, 'unit_price' => 10, 'tax_class_key' => [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, - TaxClassKeyInterface::KEY_VALUE => 'DefaultProductClass', + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, + Key::KEY_VALUE => 'DefaultProductClass', ], ]; $oneProductResults = [ @@ -649,8 +649,8 @@ class TaxCalculationTest extends \PHPUnit_Framework_TestCase ], ], 'customer_tax_class_key' => [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, - TaxClassKeyInterface::KEY_VALUE => 'DefaultCustomerClass', + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, + Key::KEY_VALUE => 'DefaultCustomerClass', ], ], 'expected_tax_details' => [ @@ -1064,8 +1064,8 @@ class TaxCalculationTest extends \PHPUnit_Framework_TestCase 'quantity' => 9, 'unit_price' => 0.33, // this is including the store tax of 10%. Pre tax is 0.3 'tax_class_key' => [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, - TaxClassKeyInterface::KEY_VALUE => 'HigherProductClass', + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, + Key::KEY_VALUE => 'HigherProductClass', ], 'tax_included' => true, ]; @@ -1817,8 +1817,8 @@ class TaxCalculationTest extends \PHPUnit_Framework_TestCase && is_string($value) ) { $value = [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, - TaxClassKeyInterface::KEY_VALUE => $this->taxClassIds[$value], + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, + Key::KEY_VALUE => $this->taxClassIds[$value], ]; } } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/ManagementTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/ManagementTest.php index 606540aa09c90b91c3b41a2c6345447a247bfd38..853a42f225c85c999748b0763388cc58d48a83e9 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/ManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/ManagementTest.php @@ -8,6 +8,7 @@ namespace Magento\Tax\Model\TaxClass; use Magento\Tax\Api\Data\TaxClassInterfaceFactory; use Magento\Tax\Api\Data\TaxClassKeyInterface; use Magento\Tax\Api\TaxClassManagementInterface; +use Magento\Tax\Model\TaxClass\Key; use Magento\TestFramework\Helper\Bootstrap; class ManagementTest extends \PHPUnit_Framework_TestCase @@ -63,8 +64,8 @@ class ManagementTest extends \PHPUnit_Framework_TestCase $this->dataObjectHelper->populateWithArray( $taxClassKeyTypeId, [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, - TaxClassKeyInterface::KEY_VALUE => $taxClassId, + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, + Key::KEY_VALUE => $taxClassId, ], '\Magento\Tax\Api\Data\TaxClassKeyInterface' ); @@ -76,8 +77,8 @@ class ManagementTest extends \PHPUnit_Framework_TestCase $this->dataObjectHelper->populateWithArray( $taxClassKeyTypeName, [ - TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, - TaxClassKeyInterface::KEY_VALUE => $taxClassName, + Key::KEY_TYPE => TaxClassKeyInterface::TYPE_NAME, + Key::KEY_VALUE => $taxClassName, ], '\Magento\Tax\Api\Data\TaxClassKeyInterface' ); diff --git a/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php b/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php index 56dfca42c97498e1a5a08510b766b7b925cfeb71..a0073fdd17b0ff1c859e85ec12dc0bc992c6f74c 100644 --- a/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php +++ b/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php @@ -60,7 +60,7 @@ class MethodsTest extends \PHPUnit_Framework_TestCase /** @var $block \Magento\Framework\View\Element\Template */ $block = $blockFactory->createBlock($blockClass); $block->setArea('frontend'); - $this->assertFileExists($block->getTemplateFile(), $message); + $this->assertFileExists((string)$block->getTemplateFile(), $message); if ($model->canUseInternal()) { try { \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( @@ -69,7 +69,7 @@ class MethodsTest extends \PHPUnit_Framework_TestCase \Magento\Store\Model\Store::DEFAULT_STORE_ID ); $block->setArea('adminhtml'); - $this->assertFileExists($block->getTemplateFile(), $message); + $this->assertFileExists((string)$block->getTemplateFile(), $message); \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( 'Magento\Store\Model\StoreManagerInterface' )->getStore()->setId( diff --git a/dev/tests/integration/testsuite/Magento/ToolkitFramework/_files/small.xml b/dev/tests/integration/testsuite/Magento/ToolkitFramework/_files/small.xml index 4c0292a8c2f0d5fd009882546a65c9258892e66c..0a0b04ba6836b74eb5d7584a9290136e540f8d8b 100644 --- a/dev/tests/integration/testsuite/Magento/ToolkitFramework/_files/small.xml +++ b/dev/tests/integration/testsuite/Magento/ToolkitFramework/_files/small.xml @@ -29,6 +29,8 @@ <!-- The price rule condition: minimum products amount in shopping cart for price rule to be applied --> <customers>20</customers> <!-- Number of customers to generate --> + <orders>80</orders> + <!-- Orders count --> <configs> <!-- Config variables and values for change --> <config> <path>admin/security/use_form_key</path> @@ -61,7 +63,7 @@ <value>0</value> </config> <config> - <path>system/full_page_cache/varnish/access_lis</path> + <path>system/full_page_cache/varnish/access_list</path> <scope>default</scope> <scopeId>0</scopeId> <value>localhost</value> @@ -79,5 +81,39 @@ <value>8080</value> </config> </configs> + <indexers> <!-- Indexer mode value (true - Update by Schedule, false - Update on Save) --> + <indexer> + <id>catalog_category_product</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_category</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_price</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_attribute</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>cataloginventory_stock</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_rule</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_product</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogsearch_fulltext</id> + <set_scheduled>false</set_scheduled> + </indexer> + </indexers> </profile> -</config> \ No newline at end of file +</config> diff --git a/dev/tests/js/jasmine/assets/apply/templates/node.html b/dev/tests/js/jasmine/assets/apply/templates/node.html index 3c6895d98c381b7d64f7210dd5b83b5e04235255..f694083783e00922b7faa63eecb5155251cc0f5a 100644 --- a/dev/tests/js/jasmine/assets/apply/templates/node.html +++ b/dev/tests/js/jasmine/assets/apply/templates/node.html @@ -5,6 +5,6 @@ */ --> <div id="<%= containerId %>"> - <div id="<%= nodeId %>" + <div id="<%= nodeId %>"> <%= dataAttr %>='<%= JSON.stringify(nodeData) %>'></div> </div> \ No newline at end of file diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/multiselect.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/multiselect.test.js new file mode 100644 index 0000000000000000000000000000000000000000..0d68a9dcfa145676d90bd99803fe11ece671d5b0 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/multiselect.test.js @@ -0,0 +1,150 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'Magento_Ui/js/grid/columns/multiselect' +], function (_, Multiselect) { + 'use strict'; + + describe('ui/js/grid/columns/multiselect', function () { + var multiSelect; + + beforeEach(function () { + multiSelect = new Multiselect({ + rows: [], + index: 'index', + name: 'name', + indexField: 'id', + dataScope: 'scope', + provider: 'provider' + }); + multiSelect.source = { + set: function () {} + }; + spyOn(multiSelect.source, 'set'); + }); + + afterEach(function () { + }); + + it('Default state - Select no rows', function () { + multiSelect.rows.push({id:1}); + multiSelect.rows.push({id:2}); + multiSelect.rows.push({id:3}); + + expect(multiSelect.allSelected()).toBeFalsy(); + expect(multiSelect.excluded()).toEqual([]); + expect(multiSelect.selected()).toEqual([]); + multiSelect.exportSelections(); + //expect(multiSelect.source.set).toHaveBeenCalledWith([]); + expect(multiSelect.source.set.calls.argsFor(1)) + .toEqual([]); + }); + + it('Select specific several rows on several pages', function () { + multiSelect.selected.push(4); + multiSelect.selected.push(5); + + expect(multiSelect.allSelected()).toBeFalsy(); + expect(multiSelect.excluded()).toEqual([]); + expect(multiSelect.selected()).toEqual([4,5]); + }); + + it('Select all rows on several pages', function () { + multiSelect.rows([ + {id:1}, + {id:2} + ]); + multiSelect.selectPage(); + multiSelect.rows([ + {id:3}, + {id:4} + ]); + multiSelect.selectPage(); + + expect(multiSelect.allSelected()).toBeFalsy(); + expect(multiSelect.excluded()).toEqual([]); + expect(multiSelect.selected()).toEqual([1,2,3,4]); + }); + + it('Select all rows on current page with some specific rows on another page', function () { + multiSelect.rows([ + {id:1}, + {id:2} + ]); + multiSelect.rows([ + {id:3}, + {id:4} + ]); + multiSelect.selectPage(); + multiSelect.rows([ + {id:5}, + {id:6} + ]); + multiSelect.selected.push(6); + + expect(multiSelect.allSelected()).toBeFalsy(); + expect(multiSelect.excluded()).toEqual([]); + expect(multiSelect.selected()).toEqual([3,4,6]); + }); + + it('Select all rows on several pages without some specific rows', function () { + multiSelect.rows([ + {id:1}, + {id:2} + ]); + multiSelect.rows([ + {id:3}, + {id:4} + ]); + multiSelect.selectPage(); + multiSelect.selected.remove(4); // remove second + + expect(multiSelect.allSelected()).toBeFalsy(); + expect(multiSelect.excluded()).toEqual([]); + expect(multiSelect.selected()).toEqual([3]); + }); + + it('Select all rows all over the Grid', function () { + multiSelect.rows([ + {id:1}, + {id:2} + ]); + multiSelect.selectAll(); + multiSelect.rows([ + {id:3}, + {id:4} + ]); + + expect(multiSelect.allSelected()).toBeFalsy(); + expect(multiSelect.excluded()).toEqual([]); + expect(multiSelect.selected()).toEqual([1,2]); + }); + + it('Select all rows all over the Grid without all rows on current page but with specific rows on another page', function () { + multiSelect.rows([ + {id:1}, + {id:2} + ]); + multiSelect.rows([ + {id:3}, + {id:4} + ]); + multiSelect.selectAll(); + multiSelect.deselectPage(); + multiSelect.rows([ + {id:5}, + {id:6} + ]); + multiSelect.selected.push(6); + + expect(multiSelect.allSelected()).toBeFalsy(); + expect(multiSelect.excluded()).toEqual([]); + expect(multiSelect.selected()).toEqual([6]); + }); + + }); +}); \ No newline at end of file diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/columns.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/columns.test.js new file mode 100644 index 0000000000000000000000000000000000000000..e01b4eb1d22910908e2540a6e8b71a7a4dad7414 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/columns.test.js @@ -0,0 +1,64 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'Magento_Ui/js/grid/controls/columns' +], function (_, Columns) { + 'use strict'; + + describe('ui/js/grid/controls/columns', function () { + var columnsInstance, + FakeElement; + + beforeEach(function () { + columnsInstance = new Columns({ + elems: [], + index: 'index', + name: 'name', + indexField: 'id', + dataScope: 'scope', + provider: 'provider' + }); + FakeElement = function(){ + return this; + }; + FakeElement.prototype.visible = function(){ + return true; + }; + }); + + it('hasOverflow method', function () { + columnsInstance.viewportSize = 2; + columnsInstance.elems.push({id:1}); + columnsInstance.elems.push({id:2}); + + expect(columnsInstance.hasOverflow()).toBeFalsy(); + + columnsInstance.elems.push({id:3}); + expect(columnsInstance.hasOverflow()).toBeTruthy(); + }); + + it('isDisabled method', function () { + columnsInstance.viewportMaxSize = 4; + columnsInstance.elems.push(new FakeElement()); + expect(columnsInstance.isDisabled(columnsInstance.elems()[0])).toBeTruthy(); + + columnsInstance.elems.push(new FakeElement()); + expect(columnsInstance.isDisabled(columnsInstance.elems()[0])).toBeFalsy(); + + columnsInstance.elems.push(new FakeElement()); + expect(columnsInstance.isDisabled(columnsInstance.elems()[0])).toBeFalsy(); + + columnsInstance.elems.push(new FakeElement()); + expect(columnsInstance.isDisabled(columnsInstance.elems()[0])).toBeFalsy(); + + columnsInstance.elems.push(new FakeElement()); + expect(columnsInstance.isDisabled(columnsInstance.elems()[0])).toBeTruthy(); + expect(columnsInstance.isDisabled(columnsInstance.elems()[3])).toBeTruthy(); + }); + + }); +}); \ No newline at end of file diff --git a/dev/tests/performance/benchmark.jmx b/dev/tests/performance/benchmark.jmx index 34b8617830f417808bcc2e5086b8ecf6efe94c72..af952a0e59cd8c3e4e8a43c08eb8af68c9287140 100644 --- a/dev/tests/performance/benchmark.jmx +++ b/dev/tests/performance/benchmark.jmx @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.6" jmeter="2.11 r1554548"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Toolkit" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -53,14 +53,14 @@ <stringProp name="Argument.value">${__P(admin_path,backend)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="admin_user" elementType="Argument"> - <stringProp name="Argument.name">admin_user</stringProp> - <stringProp name="Argument.value">${__P(admin_user,admin)}</stringProp> + <elementProp name="admin-user" elementType="Argument"> + <stringProp name="Argument.name">admin-user</stringProp> + <stringProp name="Argument.value">${__P(admin-user,admin)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="admin_password" elementType="Argument"> - <stringProp name="Argument.name">admin_password</stringProp> - <stringProp name="Argument.value">${__P(admin_password,123123q)}</stringProp> + <elementProp name="admin-password" elementType="Argument"> + <stringProp name="Argument.name">admin-password</stringProp> + <stringProp name="Argument.value">${__P(admin-password,123123q)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="response_time_file_name" elementType="Argument"> @@ -116,9 +116,10 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> <stringProp name="HTTPSampler.concurrentPool">4</stringProp> </ConfigTestElement> <hashTree/> @@ -196,15 +197,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${admin_path}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -259,14 +259,14 @@ </elementProp> <elementProp name="login[password]" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${admin_password}</stringProp> + <stringProp name="Argument.value">${admin-password}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> <stringProp name="Argument.name">login[password]</stringProp> </elementProp> <elementProp name="login[username]" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${admin_user}</stringProp> + <stringProp name="Argument.value">${admin-user}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> <stringProp name="Argument.name">login[username]</stringProp> @@ -277,15 +277,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${admin_path}</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -344,15 +343,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/cache/massDisable/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -396,7 +394,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -404,7 +402,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -431,7 +428,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -439,7 +436,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -466,7 +462,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${simple_product_url_key}${url_suffix}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -474,7 +470,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -489,7 +484,7 @@ <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product id" enabled="true"> + <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extract product id" enabled="true"> <stringProp name="XPathExtractor.default"></stringProp> <stringProp name="XPathExtractor.refname">simple_product_id</stringProp> <stringProp name="XPathExtractor.xpathQuery">.//input[@type="hidden" and @name="product"]/@value</stringProp> @@ -533,7 +528,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> @@ -541,7 +536,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -589,7 +583,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${configurable_product_url_key}${url_suffix}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -597,7 +591,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -612,7 +605,7 @@ <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product id" enabled="true"> + <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extract product id" enabled="true"> <stringProp name="XPathExtractor.default"></stringProp> <stringProp name="XPathExtractor.refname">configurable_product_id</stringProp> <stringProp name="XPathExtractor.xpathQuery">.//input[@type="hidden" and @name="product"]/@value</stringProp> @@ -621,7 +614,7 @@ <boolProp name="XPathExtractor.namespace">false</boolProp> </XPathExtractor> <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extarct product attribute id" enabled="true"> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product attribute id" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">configurable_attribute_id</stringProp> <stringProp name="RegexExtractor.regex">"spConfig":[\s]*\{"attributes":\{"(\d+)"</stringProp> @@ -630,7 +623,7 @@ <stringProp name="RegexExtractor.match_number">1</stringProp> </RegexExtractor> <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extarct product attribute option id" enabled="true"> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product attribute option id" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">configurable_option_id</stringProp> <stringProp name="RegexExtractor.regex">"options":\[\{"id":"(\d+)"</stringProp> @@ -681,7 +674,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> @@ -689,7 +682,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -737,7 +729,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -745,7 +737,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -830,15 +821,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}customer/account/loginPost/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -987,15 +977,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/saveBilling/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1058,15 +1047,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/saveShippingMethod/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1122,15 +1110,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/savePayment/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1187,15 +1174,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/saveOrder/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1222,7 +1208,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/success/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -1230,7 +1216,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1258,15 +1243,14 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}customer/account/logout/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1344,6 +1328,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename">${response_time_file_name}</stringProp> diff --git a/dev/tests/performance/config.php.dist b/dev/tests/performance/config.php.dist index e145b9768ffe2d8b6178edc2e718e0c8220d0770..38d6e0430601f293bdb20c022d7ca5ca358521fc 100644 --- a/dev/tests/performance/config.php.dist +++ b/dev/tests/performance/config.php.dist @@ -13,23 +13,23 @@ return array( 'language' => 'en_US', 'timezone' => 'America/Los_Angeles', 'currency' => 'USD', - 'db_host' => 'localhost', - 'db_name' => 'magento', - 'db_user' => 'root', - 'db_password' => '', - 'use_secure' => '0', - 'use_secure_admin' => '0', - 'use_rewrites' => '0', - 'admin_lastname' => 'Admin', - 'admin_firstname' => 'Admin', - 'admin_email' => 'admin@example.com', - 'admin_user' => 'admin', - 'admin_password' => '123123q', - 'admin_use_security_key' => '0', - 'backend_frontname' => 'backend', + 'db-host' => 'localhost', + 'db-name' => 'magento', + 'db-user' => 'root', + 'db-password' => '', + 'use-secure' => '0', + 'use-secure-admin' => '0', + 'use-rewrites' => '0', + 'admin-lastname' => 'Admin', + 'admin-firstname' => 'Admin', + 'admin-email' => 'admin@example.com', + 'admin-user' => 'admin', + 'admin-password' => '123123q', + 'admin-use-security-key' => '0', + 'backend-frontname' => 'backend', ), 'options_no_value' => array( - 'cleanup_database', + 'cleanup-database', ), ), ), diff --git a/dev/tests/performance/framework/Magento/TestFramework/Application.php b/dev/tests/performance/framework/Magento/TestFramework/Application.php index bd192386c9d747fbb5b154c615a70014c1e7ead6..031ad7194e98a14a330e0354c11b5541c672700e 100644 --- a/dev/tests/performance/framework/Magento/TestFramework/Application.php +++ b/dev/tests/performance/framework/Magento/TestFramework/Application.php @@ -156,7 +156,7 @@ class Application // Populate install options with global options $baseUrl = 'http://' . $this->_config->getApplicationUrlHost() . $this->_config->getApplicationUrlPath(); - $installOptions = array_merge($installOptions, ['base_url' => $baseUrl, 'base_url_secure' => $baseUrl]); + $installOptions = array_merge($installOptions, ['base-url' => $baseUrl, 'base-url-secure' => $baseUrl]); $installCmd = 'php -f %s setup:install'; $installCmdArgs = [$this->_script]; foreach ($installOptions as $optionName => $optionValue) { diff --git a/dev/tests/performance/framework/Magento/TestFramework/Performance/Config.php b/dev/tests/performance/framework/Magento/TestFramework/Performance/Config.php index bd01b881c6bb9bb427690147be710d7a21a1900f..65287f5656bacc9a1f78b30a3f5ae3c1e69bee6e 100644 --- a/dev/tests/performance/framework/Magento/TestFramework/Performance/Config.php +++ b/dev/tests/performance/framework/Magento/TestFramework/Performance/Config.php @@ -117,7 +117,7 @@ class Config } // Validate admin options data - $requiredAdminKeys = ['admin_user', 'admin_password', 'backend_frontname']; + $requiredAdminKeys = ['admin-user', 'admin-password', 'backend-frontname']; foreach ($requiredAdminKeys as $requiredKeyName) { if (empty($configData['application']['installation']['options'][$requiredKeyName])) { throw new \Magento\Framework\Exception\LocalizedException( @@ -277,9 +277,9 @@ class Config \Magento\TestFramework\Performance\Scenario::ARG_HOST => $this->getApplicationUrlHost(), \Magento\TestFramework\Performance\Scenario::ARG_PATH => $this->getApplicationUrlPath(), \Magento\TestFramework\Performance\Scenario::ARG_BASEDIR => $this->getApplicationBaseDir(), - \Magento\TestFramework\Performance\Scenario::ARG_BACKEND_FRONTNAME => $options['backend_frontname'], - \Magento\TestFramework\Performance\Scenario::ARG_ADMIN_USER => $options['admin_user'], - \Magento\TestFramework\Performance\Scenario::ARG_ADMIN_PASSWORD => $options['admin_password'], + \Magento\TestFramework\Performance\Scenario::ARG_BACKEND_FRONTNAME => $options['backend-frontname'], + \Magento\TestFramework\Performance\Scenario::ARG_ADMIN_USER => $options['admin-user'], + \Magento\TestFramework\Performance\Scenario::ARG_ADMIN_PASSWORD => $options['admin-password'], 'jmeter.save.saveservice.output_format' => 'xml', ]; } diff --git a/dev/tests/performance/framework/Magento/TestFramework/Performance/Scenario.php b/dev/tests/performance/framework/Magento/TestFramework/Performance/Scenario.php index ab19c64f5aebea70028fa971cd2b2c8a96995ee8..0cdbfe20936fd69c9e66a815431fc13f8c0f8770 100644 --- a/dev/tests/performance/framework/Magento/TestFramework/Performance/Scenario.php +++ b/dev/tests/performance/framework/Magento/TestFramework/Performance/Scenario.php @@ -24,11 +24,11 @@ class Scenario const ARG_BASEDIR = 'basedir'; - const ARG_ADMIN_USER = 'admin_user'; + const ARG_ADMIN_USER = 'admin-user'; - const ARG_ADMIN_PASSWORD = 'admin_password'; + const ARG_ADMIN_PASSWORD = 'admin-password'; - const ARG_BACKEND_FRONTNAME = 'backend_frontname'; + const ARG_BACKEND_FRONTNAME = 'backend-frontname'; /**#@-*/ diff --git a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/ConfigTest.php b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/ConfigTest.php index 39685b58894125220e63fd532b39f5b0f54282ac..50794f66c1cee434f92ae7b5b61b53004e2bcc6d 100644 --- a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/ConfigTest.php +++ b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/ConfigTest.php @@ -144,9 +144,9 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $expectedOptions = [ 'option1' => 'value 1', 'option2' => 'value 2', - 'backend_frontname' => 'backend', - 'admin_user' => 'admin', - 'admin_password' => 'password1', + 'backend-frontname' => 'backend', + 'admin-user' => 'admin', + 'admin-password' => 'password1', ]; $this->assertEquals($expectedOptions, $this->_object->getInstallOptions()); } diff --git a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_dist/config.php.dist b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_dist/config.php.dist index 6db1c505bff49c76b7f1472e68c6f83022d73eb4..239c3a60bec11254f1a4cfa27061480fed2b6aeb 100644 --- a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_dist/config.php.dist +++ b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_dist/config.php.dist @@ -10,9 +10,9 @@ return array( 'url_path' => '/', 'installation' => array( 'options' => array( - 'backend_frontname' => 'backend', - 'admin_user' => 'admin', - 'admin_password' => 'password1', + 'backend-frontname' => 'backend', + 'admin-user' => 'admin', + 'admin-password' => 'password1', ), ), ), diff --git a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php index 463b896d34d68ed13d2a2b1dd7c1c70e1d8e9126..07a1a86c76dece35ac4c8af990a571c82dad3708 100644 --- a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php +++ b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php @@ -10,9 +10,9 @@ return [ 'url_path' => '/', 'installation' => [ 'options' => [ - 'backend_frontname' => 'backend', - 'admin_user' => 'admin', - 'admin_password' => 'password1', + 'backend-frontname' => 'backend', + 'admin-user' => 'admin', + 'admin-password' => 'password1', ], ], ], diff --git a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php.dist b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php.dist index 577aadcc45bac471f1262da433d3ae0decc30fd3..a1b5c16c55297e28c8c78d5ac9ca75b4fee3c514 100644 --- a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php.dist +++ b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/bootstrap/config_normal/config.php.dist @@ -10,9 +10,9 @@ return array( 'url_path' => '/', 'installation' => array( 'options' => array( - 'backend_frontname' => 'backend', - 'admin_user' => 'admin', - 'admin_password' => 'password1', + 'backend-frontname' => 'backend', + 'admin-user' => 'admin', + 'admin-password' => 'password1', ), ), ), diff --git a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/config_data.php b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/config_data.php index eaa852c5e31a6ece36b932dfac4c552430aee3dd..f74eb069d8eacd093d1baaa3309ea0c4bc94b18c 100644 --- a/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/config_data.php +++ b/dev/tests/performance/framework/tests/unit/testsuite/Magento/Test/Performance/_files/config_data.php @@ -12,9 +12,9 @@ return [ 'options' => [ 'option1' => 'value 1', 'option2' => 'value 2', - 'backend_frontname' => 'backend', - 'admin_user' => 'admin', - 'admin_password' => 'password1', + 'backend-frontname' => 'backend', + 'admin-user' => 'admin', + 'admin-password' => 'password1', ], ], ], diff --git a/dev/tests/performance/testsuite/_samples/_template.jmx b/dev/tests/performance/testsuite/_samples/_template.jmx index 1effe714f7bbb3d7fa93632793245cdedad049d3..2602b87dade56c7b2bea8e561c2889da1141515b 100644 --- a/dev/tests/performance/testsuite/_samples/_template.jmx +++ b/dev/tests/performance/testsuite/_samples/_template.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.1"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -64,8 +62,10 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> </ConfigTestElement> <hashTree/> <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> @@ -101,6 +101,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> diff --git a/dev/tests/performance/testsuite/add_to_cart.jmx b/dev/tests/performance/testsuite/add_to_cart.jmx index b6a872202945507a5fa61f6792518172cea810dc..ec07b71db12101578fa518576a0652d00dd548d1 100644 --- a/dev/tests/performance/testsuite/add_to_cart.jmx +++ b/dev/tests/performance/testsuite/add_to_cart.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.1"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -60,7 +58,7 @@ </collectionProp> </Arguments> <hashTree/> - <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Add to Cart - Product View" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add to Cart - Product View" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> @@ -68,7 +66,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${product_url_key}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -78,7 +76,7 @@ <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSampler> + </HTTPSamplerProxy> <hashTree> <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract "product_id"" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> @@ -121,7 +119,7 @@ </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Cart Add Product & View Redirect" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Cart Add Product & View Redirect" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"> <elementProp name="product" elementType="HTTPArgument"> @@ -151,8 +149,8 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/product/${product_id}/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> @@ -161,7 +159,7 @@ <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSampler> + </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> @@ -175,7 +173,7 @@ <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> <stringProp name="1554014413"><a href="${base_uri}${product_url_key}">${product_name}</a></stringProp> - <stringProp name="1472794794">You added ${product_name} to your shopping cart.</stringProp> + <stringProp name="-149996652">You added ${product_name} to your shopping cart.</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -197,9 +195,11 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> <stringProp name="HTTPSampler.path">${base_path}</stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> </ConfigTestElement> <hashTree/> </hashTree> @@ -230,6 +230,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> diff --git a/dev/tests/performance/testsuite/advanced_search.jmx b/dev/tests/performance/testsuite/advanced_search.jmx index f0c4b5ea01fe28b23c71dcf980de62ac0d37af29..9b9679b2311b6bf69094920dfb2c42bc49b6ec5f 100644 --- a/dev/tests/performance/testsuite/advanced_search.jmx +++ b/dev/tests/performance/testsuite/advanced_search.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.3"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Advanced Search" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -69,7 +67,7 @@ <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> @@ -81,14 +79,13 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assertion: Header Presence" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-462078532">Advanced Search</stringProp> + <stringProp name="-1680539802">Advanced Search</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -143,19 +140,18 @@ </elementProp> </collectionProp> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}catalogsearch/advanced/result/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -215,6 +211,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> @@ -249,6 +248,21 @@ </collectionProp> </HeaderManager> <hashTree/> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> </hashTree> </hashTree> </jmeterTestPlan> diff --git a/dev/tests/performance/testsuite/backend.jmx b/dev/tests/performance/testsuite/backend.jmx index fbf480529e8084e7895f66a1541972d697f9e046..e3e9dd82a55d3060900a3368df5ee97c305086b9 100644 --- a/dev/tests/performance/testsuite/backend.jmx +++ b/dev/tests/performance/testsuite/backend.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.4" jmeter="2.9 r1437961"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Backend High Load Testing" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -22,17 +20,17 @@ </elementProp> <elementProp name="ADMIN_PATH" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PATH</stringProp> - <stringProp name="Argument.value">${__P(path,/)}${__P(backend_frontname,backend)}/</stringProp> + <stringProp name="Argument.value">${__P(path,/)}${__P(backend-frontname,backend)}/</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="ADMIN_USER" elementType="Argument"> <stringProp name="Argument.name">ADMIN_USER</stringProp> - <stringProp name="Argument.value">${__P(admin_user,admin)}</stringProp> + <stringProp name="Argument.value">${__P(admin-user,admin)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="ADMIN_PASSWORD" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PASSWORD</stringProp> - <stringProp name="Argument.value">${__P(admin_password,123123q)}</stringProp> + <stringProp name="Argument.value">${__P(admin-password,123123q)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="products_number" elementType="Argument"> @@ -88,7 +86,7 @@ <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> @@ -100,14 +98,13 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Total Number of Products" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1786510475"><h1 class="title">Products</h1></stringProp> + <stringProp name="658046956"><h1 class="title">Products</h1></stringProp> <stringProp name="-1952867632">Total ${products_number} records found</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> @@ -120,26 +117,25 @@ <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${ADMIN_PATH}customer/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Total Number of Customers" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-5737002"><h1 class="title">Customers</h1></stringProp> + <stringProp name="-1533867969"><h1 class="title">Customers</h1></stringProp> <stringProp name="1843270971">Total ${customers_number} records found</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> @@ -152,19 +148,18 @@ <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${ADMIN_PATH}sales/order/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -185,6 +180,21 @@ <boolProp name="CookieManager.clearEachIteration">true</boolProp> </CookieManager> <hashTree/> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="false"> <boolProp name="ResultCollector.error_logging">false</boolProp> <objProp> @@ -212,6 +222,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> diff --git a/dev/tests/performance/testsuite/category_view.jmx b/dev/tests/performance/testsuite/category_view.jmx index c5954e9be980fd0b3cb30a2db248413238bc2f6e..5697ace521dd272df24023823501f3378d6998e2 100644 --- a/dev/tests/performance/testsuite/category_view.jmx +++ b/dev/tests/performance/testsuite/category_view.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.2"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Category View" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -64,11 +62,11 @@ <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}${CATEGORY_URI}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -76,7 +74,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -105,7 +102,7 @@ <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> <stringProp name="-1004972625">Category 1</stringProp> - <stringProp name="952135968">Simple Product</stringProp> + <stringProp name="1413426305">Simple Product</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -114,6 +111,21 @@ <hashTree/> </hashTree> </hashTree> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="false"> <boolProp name="ResultCollector.error_logging">false</boolProp> <objProp> @@ -141,6 +153,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> diff --git a/dev/tests/performance/testsuite/checkout.jmx b/dev/tests/performance/testsuite/checkout.jmx index 5dda04cb25a9e0a66328da0833506d92c7f7a71a..6306e47f71ab4d71d780ea77e958cfea918d27c8 100644 --- a/dev/tests/performance/testsuite/checkout.jmx +++ b/dev/tests/performance/testsuite/checkout.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.3"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="One Page Checkout" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -42,17 +40,17 @@ </elementProp> <elementProp name="ADMIN_PATH" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PATH</stringProp> - <stringProp name="Argument.value">${__P(path,/)}${__P(backend_frontname,backend)}/</stringProp> + <stringProp name="Argument.value">${__P(path,/)}${__P(backend-frontname,backend)}/</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="ADMIN_USER" elementType="Argument"> <stringProp name="Argument.name">ADMIN_USER</stringProp> - <stringProp name="Argument.value">${__P(admin_user,admin)}</stringProp> + <stringProp name="Argument.value">${__P(admin-user,admin)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="ADMIN_PASSWORD" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PASSWORD</stringProp> - <stringProp name="Argument.value">${__P(admin_password,123123q)}</stringProp> + <stringProp name="Argument.value">${__P(admin-password,123123q)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -74,7 +72,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${ADMIN_PATH}sales/order/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -82,7 +80,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -172,7 +169,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -250,14 +246,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/cart/add/product/${product_id}/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -307,7 +302,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -339,14 +333,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/saveMethod/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -526,14 +519,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/saveBilling/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -586,14 +578,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/getAdditional/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -648,7 +639,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -692,14 +682,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/saveShippingMethod/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -752,14 +741,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/progress/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -799,14 +787,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/savePayment/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -859,14 +846,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/progress/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -914,14 +900,13 @@ <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${PATH}checkout/onepage/saveOrder/</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -981,7 +966,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1067,6 +1051,9 @@ if (numAfter !== null) { // The asserion is called for every sampler, but we wan <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> @@ -1081,8 +1068,9 @@ if (numAfter !== null) { // The asserion is called for every sampler, but we wan <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> <stringProp name="HTTPSampler.concurrentPool">4</stringProp> </ConfigTestElement> <hashTree/> diff --git a/dev/tests/performance/testsuite/fixtures/catalog_category_flat_enabled.php b/dev/tests/performance/testsuite/fixtures/catalog_category_flat_enabled.php index 00cd8ce5cb1d148ff81ebcad4ad463fd1933df2f..056fe99b815516c7bb1b20181297a78013312268 100644 --- a/dev/tests/performance/testsuite/fixtures/catalog_category_flat_enabled.php +++ b/dev/tests/performance/testsuite/fixtures/catalog_category_flat_enabled.php @@ -3,6 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ +use Magento\Framework\App\Config\ScopeConfigInterface; /** @var \Magento\TestFramework\Application $this */ @@ -13,7 +14,7 @@ $configData = $this->getObjectManager()->create('Magento\Framework\App\Config\Va $configData->setPath( 'catalog/frontend/flat_catalog_category' )->setScope( - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT )->setScopeId( 0 )->setValue( diff --git a/dev/tests/performance/testsuite/fixtures/catalog_product_flat_enabled.php b/dev/tests/performance/testsuite/fixtures/catalog_product_flat_enabled.php index 2258e72023d4ad642e1e799134e8b32cbb94d1ab..e06ed0e26c053f2742d6a132f17b4a0f4b8558ce 100644 --- a/dev/tests/performance/testsuite/fixtures/catalog_product_flat_enabled.php +++ b/dev/tests/performance/testsuite/fixtures/catalog_product_flat_enabled.php @@ -3,6 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ +use Magento\Framework\App\Config\ScopeConfigInterface; /** @var \Magento\TestFramework\Application $this */ @@ -13,7 +14,7 @@ $configData = $this->getObjectManager()->create('Magento\Framework\App\Config\Va $configData->setPath( 'catalog/frontend/flat_catalog_product' )->setScope( - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT )->setScopeId( 0 )->setValue( diff --git a/dev/tests/performance/testsuite/fixtures/shipping_flatrate_enabled.php b/dev/tests/performance/testsuite/fixtures/shipping_flatrate_enabled.php index e0f50505c4adcf397a358a5d8d31e336bd00a3e6..15b445ce1f8b5ca75cf4b6eb1ae20a179bcfa356 100644 --- a/dev/tests/performance/testsuite/fixtures/shipping_flatrate_enabled.php +++ b/dev/tests/performance/testsuite/fixtures/shipping_flatrate_enabled.php @@ -3,6 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ +use Magento\Framework\App\Config\ScopeConfigInterface; /** @var \Magento\TestFramework\Application $this */ @@ -13,7 +14,7 @@ $configData = $this->getObjectManager()->create('Magento\Framework\App\Config\Va $configData->setPath( 'carriers/flatrate/active' )->setScope( - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT )->setScopeId( 0 )->setValue( diff --git a/dev/tests/performance/testsuite/home_page.jmx b/dev/tests/performance/testsuite/home_page.jmx index 91f82ddcaecc43aa548b832ad6a83bdeb714ccea..b335bdceb5ac27c8275ba7791b7f0e423ff75c52 100644 --- a/dev/tests/performance/testsuite/home_page.jmx +++ b/dev/tests/performance/testsuite/home_page.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.5" jmeter="2.10 r1533061"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -53,7 +51,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -61,7 +59,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -105,11 +102,29 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> </ResultCollector> <hashTree/> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"></stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> </hashTree> </hashTree> </jmeterTestPlan> diff --git a/dev/tests/performance/testsuite/product_edit.jmx b/dev/tests/performance/testsuite/product_edit.jmx index 199c36235c16396d48dcfed93ed116ec14dd5b72..c4b2ced13478c5ee364d629957529ee46d23c619 100644 --- a/dev/tests/performance/testsuite/product_edit.jmx +++ b/dev/tests/performance/testsuite/product_edit.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.3"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Admin - Edit Product" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -22,7 +20,7 @@ </elementProp> <elementProp name="ADMIN_PATH" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PATH</stringProp> - <stringProp name="Argument.value">${__P(path,/)}${__P(backend_frontname,backend)}/</stringProp> + <stringProp name="Argument.value">${__P(path,/)}${__P(backend-frontname,backend)}/</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="USERS" elementType="Argument"> @@ -37,12 +35,12 @@ </elementProp> <elementProp name="ADMIN_USER" elementType="Argument"> <stringProp name="Argument.name">ADMIN_USER</stringProp> - <stringProp name="Argument.value">${__P(admin_user,admin)}</stringProp> + <stringProp name="Argument.value">${__P(admin-user,admin)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="ADMIN_PASSWORD" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PASSWORD</stringProp> - <stringProp name="Argument.value">${__P(admin_password,123123q)}</stringProp> + <stringProp name="Argument.value">${__P(admin-password,123123q)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="product_sku" elementType="Argument"> @@ -100,11 +98,11 @@ </elementProp> </collectionProp> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${ADMIN_PATH}catalog/product/grid/product_filter/${grid_product_filter}/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -112,7 +110,6 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -163,11 +160,11 @@ vars.put("grid_product_filter", gridProductFilter);</stringProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${ADMIN_PATH}catalog/product/edit/id/${product_id}/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -175,7 +172,6 @@ vars.put("grid_product_filter", gridProductFilter);</stringProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -193,6 +189,21 @@ vars.put("grid_product_filter", gridProductFilter);</stringProp> </ResponseAssertion> <hashTree/> </hashTree> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> <collectionProp name="CookieManager.cookies"/> <boolProp name="CookieManager.clearEachIteration">true</boolProp> @@ -226,6 +237,9 @@ vars.put("grid_product_filter", gridProductFilter);</stringProp> <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> diff --git a/dev/tests/performance/testsuite/product_view.jmx b/dev/tests/performance/testsuite/product_view.jmx index 44598d85913f78269299018dd404c4a1d22c9a6a..218f3478b1101a1fba42b6fed7ee60cd770b7dac 100644 --- a/dev/tests/performance/testsuite/product_view.jmx +++ b/dev/tests/performance/testsuite/product_view.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.1"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Product View" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -55,15 +53,15 @@ <stringProp name="ThreadGroup.delay"></stringProp> </ThreadGroup> <hashTree> - <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Product View" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Product View" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain">${base_host}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${base_path}${product_url_key}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -73,7 +71,7 @@ <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSampler> + </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> @@ -86,6 +84,21 @@ <hashTree/> </hashTree> </hashTree> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${base_host}</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="false"> <boolProp name="ResultCollector.error_logging">false</boolProp> <objProp> @@ -113,6 +126,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> diff --git a/dev/tests/performance/testsuite/quick_search.jmx b/dev/tests/performance/testsuite/quick_search.jmx index 8aaf25840e63788e5bd9e391352801222c55a4db..82ab754249e5b72acc767bdb30f25db1faf2b8da 100644 --- a/dev/tests/performance/testsuite/quick_search.jmx +++ b/dev/tests/performance/testsuite/quick_search.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.1"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Quick Search" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -60,7 +58,7 @@ <stringProp name="ThreadGroup.delay"></stringProp> </ThreadGroup> <hashTree> - <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Quick Search" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Quick Search" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"> <elementProp name="q" elementType="HTTPArgument"> @@ -72,7 +70,7 @@ </elementProp> </collectionProp> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> @@ -86,7 +84,7 @@ <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSampler> + </HTTPSamplerProxy> <hashTree> <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> <collectionProp name="HeaderManager.headers"> @@ -119,7 +117,7 @@ <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-887183200">Search results for: '${search_query}'</stringProp> + <stringProp name="-382529492">Search results for: '${search_query}'</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -128,6 +126,21 @@ <hashTree/> </hashTree> </hashTree> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> <collectionProp name="CookieManager.cookies"/> <boolProp name="CookieManager.clearEachIteration">true</boolProp> diff --git a/dev/tests/performance/testsuite/reusable/admin_login.jmx b/dev/tests/performance/testsuite/reusable/admin_login.jmx index 6d271217d8989d6d97eb0aaf52f9627c5ddcb9f8..9d6eb8fb2cb2e2d23d120603de002bcd3ab108dc 100644 --- a/dev/tests/performance/testsuite/reusable/admin_login.jmx +++ b/dev/tests/performance/testsuite/reusable/admin_login.jmx @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** - * @category Magento - * @package performance_tests * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.4" jmeter="2.9 r1437961"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Admin - Login" enabled="true"> <stringProp name="TestPlan.comments">Reusable scenario to log-in to admin backend. Needs: HOST, ADMIN_PATH, ADMIN_USER, ADMIN_PASSWORD, Http Cookie Manager</stringProp> @@ -29,7 +27,7 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${ADMIN_PATH}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> @@ -37,14 +35,13 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert login form shown" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1661392365">Log into Magento Admin Page</stringProp> + <stringProp name="731356397">Log into Magento Admin Page</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -91,11 +88,11 @@ </elementProp> </collectionProp> </elementProp> - <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.domain"></stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">${ADMIN_PATH}</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> @@ -103,14 +100,13 @@ <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert logged-in" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="934841248">${ADMIN_USER}</stringProp> + <stringProp name="-348322869">${ADMIN_USER}</stringProp> <stringProp name="-989788387">Account Setting</stringProp> <stringProp name="374398571">Sign Out</stringProp> </collectionProp> @@ -159,23 +155,38 @@ </elementProp> <elementProp name="ADMIN_PATH" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PATH</stringProp> - <stringProp name="Argument.value">${__P(path,/)}${__P(backend_frontname,backend)}/</stringProp> + <stringProp name="Argument.value">${__P(path,/)}${__P(backend-frontname,backend)}/</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="ADMIN_USER" elementType="Argument"> <stringProp name="Argument.name">ADMIN_USER</stringProp> - <stringProp name="Argument.value">${__P(admin_user,admin)}</stringProp> + <stringProp name="Argument.value">${__P(admin-user,admin)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="ADMIN_PASSWORD" elementType="Argument"> <stringProp name="Argument.name">ADMIN_PASSWORD</stringProp> - <stringProp name="Argument.value">${__P(admin_password,123123q)}</stringProp> + <stringProp name="Argument.value">${__P(admin-password,123123q)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> </Arguments> <hashTree/> </hashTree> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${HOST}</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true"> <boolProp name="ResultCollector.error_logging">false</boolProp> <objProp> @@ -203,6 +214,9 @@ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename"></stringProp> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Readme/_files/blacklist/ce.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/Readme/_files/blacklist/ce.txt index 2fd6ad123621cb9b830d5d02b3840463d4520fbc..564d756255d7e6b7be5db625ccf8ebb0e634a026 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Readme/_files/blacklist/ce.txt +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Readme/_files/blacklist/ce.txt @@ -35,5 +35,6 @@ lib/internal/Magento/Framework/System lib/internal/Magento/Framework/Test lib/internal/Magento/Framework/App/Utility lib/internal/Magento/Framework/Url +lib/internal/Magento/Framework/UrlInterface lib/internal/Magento/Framework/Xml lib/internal/Magento/Framework diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/LayoutTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/LayoutTest.php index ae89d5ddb32941c6dace4b041fe459153a34a6cb..28353e7f953138cfa0dd3d91b04c17f70062e07a 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/LayoutTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/LayoutTest.php @@ -316,7 +316,6 @@ class LayoutTest extends \PHPUnit_Framework_TestCase 'setListOrders', 'setMAPTemplate', 'setMethodFormTemplate', - 'setMethodInfo', 'setMyClass', 'setPageLayout', 'setPageTitle', diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php index a3fa40a7f43a6718bc2949067c23dd314b874c11..b0e6f2627029a8da911b3e6a4358c3aff4f133af 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_constants.php @@ -702,4 +702,26 @@ return [ 'Use \Magento\Eav\Model\Entity\Type::getDefaultAttributeSetId() method instead', ], ['CONFIG_PATH_WSDL_CACHE_ENABLED', 'Magento\Webapi\Model\Soap\Server'], + ['ENTITY', 'Magento\Framework\App\Config\ValueInterface'], + ['XML_PATH_ALLOW_CURRENCIES_INSTALLED', 'Magento\Framework\Locale\CurrencyInterface'], + [ + 'DEFAULT_CURRENCY', + 'Magento\Framework\Locale\CurrencyInterface', + 'Magento\Framework\Locale\Currency::DEFAULT_CURRENCY' + ], + [ + 'DEFAULT_LOCALE', + 'Magento\Framework\Locale\ResolverInterface', + 'Magento\Framework\Locale\Resolver::DEFAULT_LOCALE' + ], + [ + 'DEFAULT_GROUP', + 'Magento\Framework\Message\ManagerInterface', + 'Magento\Framework\Message\Manager::DEFAULT_GROUP' + ], + [ + 'SCOPE_DEFAULT', + 'Magento\Framework\App\ScopeInterface', + 'Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT' + ] ]; diff --git a/dev/tests/unit/framework/bootstrap.php b/dev/tests/unit/framework/bootstrap.php index b30486b50a17dc3a6e0b67adaa072868b1747736..45ae70bc21fbb39fc79b347cc4749a6243d18d7f 100755 --- a/dev/tests/unit/framework/bootstrap.php +++ b/dev/tests/unit/framework/bootstrap.php @@ -6,6 +6,11 @@ require_once __DIR__ . '/../../../../app/autoload.php'; +$updateAppBootstrap = __DIR__ . '/../../../../update/app/bootstrap.php'; +if (file_exists($updateAppBootstrap)) { + require_once $updateAppBootstrap; +} + if (!defined('TESTS_TEMP_DIR')) { define('TESTS_TEMP_DIR', dirname(__DIR__) . '/tmp'); } diff --git a/dev/tests/unit/phpunit.xml.dist b/dev/tests/unit/phpunit.xml.dist index 5c785e252e48aa8c82aa8bcfe817c761b38ecc23..4c5587187da794847e7e0e6c47157106193a14fd 100644 --- a/dev/tests/unit/phpunit.xml.dist +++ b/dev/tests/unit/phpunit.xml.dist @@ -17,6 +17,7 @@ <directory suffix="Test.php">../../../lib/internal/*/*/Test/Unit</directory> <directory suffix="Test.php">../../../lib/internal/*/*/*/Test/Unit</directory> <directory suffix="Test.php">../../../setup/src/*/*/Test/Unit</directory> + <directory suffix="Test.php">../../../update/dev/tests/unit/testsuite</directory> </testsuite> <php> <ini name="date.timezone" value="America/Los_Angeles"/> @@ -26,6 +27,7 @@ <directory suffix=".php">../../../app/code/*</directory> <directory suffix=".php">../../../lib/internal/Magento</directory> <directory suffix=".php">../../../setup/src/*</directory> + <directory suffix=".php">../../../update/app/code/*</directory> <exclude> <directory>../../../app/code/*/*/Test</directory> <directory>../../../lib/internal/*/*/Test</directory> diff --git a/dev/tools/performance-toolkit/fixtures/indexers_states_apply.php b/dev/tools/performance-toolkit/fixtures/indexers_states_apply.php new file mode 100644 index 0000000000000000000000000000000000000000..8b072e2b68995399e051ab77cf868efb15638630 --- /dev/null +++ b/dev/tools/performance-toolkit/fixtures/indexers_states_apply.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Class IndexersStatesApplyFixture + */ +class IndexersStatesApplyFixture extends \Magento\ToolkitFramework\Fixture +{ + /** + * @var int + */ + protected $priority = 170; + + /** + * {@inheritdoc} + */ + public function execute() + { + $indexers = \Magento\ToolkitFramework\Config::getInstance()->getValue('indexers', []); + if (!isset($indexers["indexer"]) || empty($indexers["indexer"])) { + return; + } + $this->application->resetObjectManager(); + foreach ($indexers["indexer"] as $indexer) { + $this->application->indexersStates[$indexer['id']] = ($indexer['set_scheduled'] == "true"); + } + $this->application->getObjectManager()->get('Magento\Framework\App\CacheInterface') + ->clean([\Magento\Framework\App\Config::CACHE_TAG]); + } + + /** + * {@inheritdoc} + */ + public function getActionTitle() + { + return 'Indexers Mode Changes'; + } + + /** + * {@inheritdoc} + */ + public function introduceParamLabels() + { + return []; + } +} + +return new IndexersStatesApplyFixture($this); diff --git a/dev/tools/performance-toolkit/fixtures/orders.php b/dev/tools/performance-toolkit/fixtures/orders.php new file mode 100644 index 0000000000000000000000000000000000000000..041fcea755125f106f7715913c5bfe13b1dff926 --- /dev/null +++ b/dev/tools/performance-toolkit/fixtures/orders.php @@ -0,0 +1,314 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Class OrdersFixture + */ +class OrdersFixture extends \Magento\ToolkitFramework\Fixture +{ + /** + * @var int + */ + protected $priority = 135; + + /** + * {@inheritdoc} + */ + public function execute() + { + $ordersCount = \Magento\ToolkitFramework\Config::getInstance()->getValue('orders', 0); + if ($ordersCount < 1) { + return; + } + $this->application->resetObjectManager(); + + $writeAdapter = $this->getConnection('write'); + + $quoteTableName = $this->getTableName( + 'quote', + 'Magento\Quote\Model\Resource\Quote' + ); + $quoteAddressTableName = $this->getTableName( + 'quote_address', + 'Magento\Quote\Model\Resource\Quote\Address' + ); + $quoteItemTableName = $this->getTableName( + 'quote_item', + 'Magento\Quote\Model\Resource\Quote\Item' + ); + $quoteItemOptionTableName = $this->getTableName( + 'quote_item_option', + 'Magento\Quote\Model\Resource\Quote\Item\Option' + ); + $quotePaymentTableName = $this->getTableName( + 'quote_payment', + 'Magento\Quote\Model\Resource\Quote\Payment' + ); + $quoteAddressRateTableName = $this->getTableName( + 'quote_shipping_rate', + 'Magento\Quote\Model\Resource\Quote\Address\Rate' + ); + $reportEventTableName = $this->getTableName( + 'report_event', + 'Magento\Reports\Model\Resource\Event' + ); + $salesOrderTableName = $this->getTableName( + 'sales_order', + 'Magento\Sales\Model\Resource\Order' + ); + $salesOrderAddressTableName = $this->getTableName( + 'sales_order_address', + 'Magento\Sales\Model\Resource\Order' + ); + $salesOrderGridTableName = $this->getTableName( + 'sales_order_grid', + 'Magento\Sales\Model\Resource\Order\Grid' + ); + $salesOrderItemTableName = $this->getTableName( + 'sales_order_item', + 'Magento\Sales\Model\Resource\Order\Item' + ); + $salesOrderPaymentTableName = $this->getTableName( + 'sales_order_payment', + 'Magento\Sales\Model\Resource\Order\Payment' + ); + $salesOrderStatusHistoryTableName = $this->getTableName( + 'sales_order_status_history', + 'Magento\Sales\Model\Resource\Order\Status\History' + ); + $eavEntityStoreTableName = $this->getTableName( + 'eav_entity_store', + '\Magento\Eav\Model\Resource\Entity\Store' + ); + /** @var \Magento\Store\Model\StoreManager $storeManager */ + $storeManager = $this->application->getObjectManager()->create('Magento\Store\Model\StoreManager'); + /** @var $category \Magento\Catalog\Model\Category */ + $category = $this->application->getObjectManager()->get('Magento\Catalog\Model\Category'); + /** @var $product \Magento\Catalog\Model\Product */ + $product = $this->application->getObjectManager()->get('Magento\Catalog\Model\Product'); + + $result = []; + $stores = $storeManager->getStores(); + foreach ($stores as $store) { + $storeId = $store->getStoreId(); + $websiteId = $store->getWebsite()->getId(); + $websiteName = $store->getWebsite()->getName(); + $groupName = $store->getGroup()->getName(); + $storeName = $store->getName(); + $storeRootCategory = $store->getRootCategoryId(); + $category->load($storeRootCategory); + $categoryResource = $category->getResource(); + //Get all categories + $resultsCategories = $categoryResource->getAllChildren($category); + foreach ($resultsCategories as $resultsCategory) { + $category->load($resultsCategory); + $structure = explode('/', $category->getPath()); + $pathSize = count($structure); + if ($pathSize > 1) { + $path = []; + for ($i = 1; $i < $pathSize; $i++) { + $path[] = $category->load($structure[$i])->getName(); + } + array_shift($path); + $resultsCategoryName = implode('/', $path); + } else { + $resultsCategoryName = $category->getName(); + } + //Not use root categories + if (trim($resultsCategoryName) != '') { + /** @var $productCategory \Magento\Catalog\Model\Category */ + $productCategory = $this->application->getObjectManager()->get('Magento\Catalog\Model\Category'); + + /** @var $simpleProductCollection \Magento\Catalog\Model\Resource\Product\Collection */ + $simpleProductCollection = $this->application->getObjectManager()->create( + 'Magento\Catalog\Model\Resource\Product\Collection' + ); + + $simpleProductCollection->addStoreFilter($storeId); + $simpleProductCollection->addWebsiteFilter($websiteId); + $simpleProductCollection->addCategoryFilter($productCategory->load($resultsCategory)); + $simpleProductCollection->getSelect()->where(" type_id = 'simple' "); + $simpleIds = $simpleProductCollection->getAllIds(2); + $simpleProductsResult = []; + foreach ($simpleIds as $key => $simpleId) { + $simpleProduct = $product->load($simpleId); + $simpleProductsResult[$key]['simpleProductId'] = $simpleId; + $simpleProductsResult[$key]['simpleProductSku'] = $simpleProduct->getSku(); + $simpleProductsResult[$key]['simpleProductName'] = $simpleProduct->getName(); + } + + $result[] = [ + $storeId, + $websiteName. '\n'. $groupName . '\n' . $storeName, + $simpleProductsResult + ]; + } + } + } + + $productStoreId = function ($index) use ($result) { + return $result[$index % count($result)][0]; + }; + $productStoreName = function ($index) use ($result) { + return $result[$index % count($result)][1]; + }; + + $simpleProductId[0] = function ($index) use ($result) { + return $result[$index % count($result)][2][0]['simpleProductId']; + }; + $simpleProductId[1] = function ($index) use ($result) { + return $result[$index % count($result)][2][1]['simpleProductId']; + }; + $simpleProductSku[0] = function ($index) use ($result) { + return $result[$index % count($result)][2][0]['simpleProductSku']; + }; + $simpleProductSku[1] = function ($index) use ($result) { + return $result[$index % count($result)][2][1]['simpleProductSku']; + }; + $simpleProductName[0] = function ($index) use ($result) { + return $result[$index % count($result)][2][0]['simpleProductName']; + }; + $simpleProductName[1] = function ($index) use ($result) { + return $result[$index % count($result)][2][1]['simpleProductName']; + }; + + $entityId = 1; + while ($entityId <= $ordersCount) { + $queries = ""; + + $orderNumber = 100000000 * $productStoreId($entityId) + $entityId; + $email = 'order_' . $entityId . '@example.com'; + $firstName = 'First Name'; + $lastName = 'Last Name'; + $company = 'Company'; + $address = 'Address'; + $city = 'City'; + $state = 'Alabama'; + $country = 'US'; + $zip = '11111'; + $phone = '911'; + $time = date("Y-m-d h:i:s"); + + $simpleProductIdLen[0] = strlen($simpleProductId[0]($entityId)); + $simpleProductIdLen[1] = strlen($simpleProductId[1]($entityId)); + + $queries .= "INSERT INTO `{$eavEntityStoreTableName}` (`entity_store_id`, `entity_type_id`, `store_id`, `increment_prefix`, `increment_last_id`) VALUES ({$productStoreId($entityId)}, 5, {$productStoreId($entityId)}, '{$productStoreId($entityId)}', '{$orderNumber}') ON DUPLICATE KEY UPDATE `increment_last_id`='{$orderNumber}';"; + + $quoteId = $entityId; + $queries .= "INSERT INTO `{$quoteTableName}` (`entity_id`, `store_id`, `created_at`, `updated_at`, `converted_at`, `is_active`, `is_virtual`, `is_multi_shipping`, `items_count`, `items_qty`, `orig_order_id`, `store_to_base_rate`, `store_to_quote_rate`, `base_currency_code`, `store_currency_code`, `quote_currency_code`, `grand_total`, `base_grand_total`, `checkout_method`, `customer_id`, `customer_tax_class_id`, `customer_group_id`, `customer_email`, `customer_prefix`, `customer_firstname`, `customer_middlename`, `customer_lastname`, `customer_suffix`, `customer_dob`, `customer_note`, `customer_note_notify`, `customer_is_guest`, `remote_ip`, `applied_rule_ids`, `reserved_order_id`, `password_hash`, `coupon_code`, `global_currency_code`, `base_to_global_rate`, `base_to_quote_rate`, `customer_taxvat`, `customer_gender`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `is_changed`, `trigger_recollect`, `ext_shipping_info`, `is_persistent`, `gift_message_id`) VALUES ({$quoteId}, {$productStoreId($entityId)}, '{$time}', '1970-01-01 03:00:00', NULL, 0, 0, 0, 2, 2.0000, 0, 0.0000, 0.0000, 'USD', 'USD', 'USD', 25.3000, 25.3000, 'guest', NULL, 3, 0, '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, '127.0.0.1', '1', NULL, NULL, NULL, 'USD', 1.0000, 1.0000, NULL, NULL, 17.0000, 17.0000, 15.3000, 15.3000, 1, 0, NULL, 0, NULL);"; + + $quoteAddressId[0] = $entityId * 2 - 1; + $quoteAddressId[1] = $entityId * 2; + $queries .= "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `shipping_hidden_tax_amount`, `base_shipping_hidden_tax_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[0]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 1, NULL, 'billing', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 0, 0, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `shipping_hidden_tax_amount`, `base_shipping_hidden_tax_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[1]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 0, NULL, 'shipping', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 1, 0, 'flatrate_flatrate', 'Flat Rate - Fixed', 2.0000, 17.0000, 17.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 10.0000, 0.0000, 0.0000, -1.7000, -1.7000, 25.3000, 25.3000, NULL, 'a:0:{}', NULL, 0.0000, 0.0000, 17.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, 10.0000, 10.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; + + $quoteItemId[0] = $entityId * 4 - 3; + $quoteItemId[1] = $entityId * 4 - 2; + $quoteItemId[2] = $entityId * 4 - 1; + $quoteItemId[3] = $entityId * 4; + $queries .= "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[0]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[0]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[1]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[1]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + + $quoteItemOptionId[0] = $entityId * 8 - 7; + $quoteItemOptionId[1] = $entityId * 8 - 6; + $quoteItemOptionId[2] = $entityId * 8 - 5; + $quoteItemOptionId[3] = $entityId * 8 - 4; + $quoteItemOptionId[4] = $entityId * 8 - 3; + $quoteItemOptionId[5] = $entityId * 8 - 2; + $quoteItemOptionId[6] = $entityId * 8 - 1; + $quoteItemOptionId[7] = $entityId * 8; + $queries .= "INSERT INTO `{$quoteItemOptionTableName}` (`option_id`, `item_id`, `product_id`, `code`, `value`) VALUES ({$quoteItemOptionId[0]}, {$quoteItemId[0]}, {$simpleProductId[0]($entityId)}, 'info_buyRequest', 'a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}');"; + $queries .= "INSERT INTO `{$quoteItemOptionTableName}` (`option_id`, `item_id`, `product_id`, `code`, `value`) VALUES ({$quoteItemOptionId[1]}, {$quoteItemId[1]}, {$simpleProductId[1]($entityId)}, 'info_buyRequest', 'a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}');"; + + $quotePaymentId = $quoteId; + $queries .= "INSERT INTO `{$quotePaymentTableName}` (`payment_id`, `quote_id`, `created_at`, `updated_at`, `method`, `cc_type`, `cc_number_enc`, `cc_last_4`, `cc_cid_enc`, `cc_owner`, `cc_exp_month`, `cc_exp_year`, `cc_ss_owner`, `cc_ss_start_month`, `cc_ss_start_year`, `po_number`, `additional_data`, `cc_ss_issue`, `additional_information`) VALUES ({$quotePaymentId}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', 'checkmo', NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, NULL, NULL, NULL, NULL);"; + + $quoteShippingRateId = $quoteAddressId[1]; + $queries .= "INSERT INTO `{$quoteAddressRateTableName}` (`rate_id`, `address_id`, `created_at`, `updated_at`, `carrier`, `carrier_title`, `code`, `method`, `method_description`, `price`, `error_message`, `method_title`) VALUES ({$quoteShippingRateId}, {$quoteAddressId[1]}, '{$time}', '1970-01-01 03:00:00', 'flatrate', 'Flat Rate', 'flatrate_flatrate', 'flatrate', NULL, 10.0000, NULL, 'Fixed');"; + + $reportEventId[0] = $quoteItemId[0]; + $reportEventId[1] = $quoteItemId[1]; + $reportEventId[2] = $quoteItemId[2]; + $reportEventId[3] = $quoteItemId[3]; + $queries .= "INSERT INTO `{$reportEventTableName}` (`event_id`, `logged_at`, `event_type_id`, `object_id`, `subject_id`, `subtype`, `store_id`) VALUES ({$reportEventId[0]}, '{$time}', 4, {$simpleProductId[0]($entityId)}, 2, 1, {$productStoreId($entityId)});"; + $queries .= "INSERT INTO `{$reportEventTableName}` (`event_id`, `logged_at`, `event_type_id`, `object_id`, `subject_id`, `subtype`, `store_id`) VALUES ({$reportEventId[1]}, '{$time}', 4, {$simpleProductId[1]($entityId)}, 2, 1, {$productStoreId($entityId)});"; + + $salesOrderId = $quoteId; + $queries .= "INSERT INTO `{$salesOrderTableName}` (`entity_id`, `state`, `status`, `coupon_code`, `protect_code`, `shipping_description`, `is_virtual`, `store_id`, `customer_id`, `base_discount_amount`, `base_discount_canceled`, `base_discount_invoiced`, `base_discount_refunded`, `base_grand_total`, `base_shipping_amount`, `base_shipping_canceled`, `base_shipping_invoiced`, `base_shipping_refunded`, `base_shipping_tax_amount`, `base_shipping_tax_refunded`, `base_subtotal`, `base_subtotal_canceled`, `base_subtotal_invoiced`, `base_subtotal_refunded`, `base_tax_amount`, `base_tax_canceled`, `base_tax_invoiced`, `base_tax_refunded`, `base_to_global_rate`, `base_to_order_rate`, `base_total_canceled`, `base_total_invoiced`, `base_total_invoiced_cost`, `base_total_offline_refunded`, `base_total_online_refunded`, `base_total_paid`, `base_total_qty_ordered`, `base_total_refunded`, `discount_amount`, `discount_canceled`, `discount_invoiced`, `discount_refunded`, `grand_total`, `shipping_amount`, `shipping_canceled`, `shipping_invoiced`, `shipping_refunded`, `shipping_tax_amount`, `shipping_tax_refunded`, `store_to_base_rate`, `store_to_order_rate`, `subtotal`, `subtotal_canceled`, `subtotal_invoiced`, `subtotal_refunded`, `tax_amount`, `tax_canceled`, `tax_invoiced`, `tax_refunded`, `total_canceled`, `total_invoiced`, `total_offline_refunded`, `total_online_refunded`, `total_paid`, `total_qty_ordered`, `total_refunded`, `can_ship_partially`, `can_ship_partially_item`, `customer_is_guest`, `customer_note_notify`, `billing_address_id`, `customer_group_id`, `edit_increment`, `email_sent`, `send_email`, `forced_shipment_with_invoice`, `payment_auth_expiration`, `quote_address_id`, `quote_id`, `shipping_address_id`, `adjustment_negative`, `adjustment_positive`, `base_adjustment_negative`, `base_adjustment_positive`, `base_shipping_discount_amount`, `base_subtotal_incl_tax`, `base_total_due`, `payment_authorization_amount`, `shipping_discount_amount`, `subtotal_incl_tax`, `total_due`, `weight`, `customer_dob`, `increment_id`, `applied_rule_ids`, `base_currency_code`, `customer_email`, `customer_firstname`, `customer_lastname`, `customer_middlename`, `customer_prefix`, `customer_suffix`, `customer_taxvat`, `discount_description`, `ext_customer_id`, `ext_order_id`, `global_currency_code`, `hold_before_state`, `hold_before_status`, `order_currency_code`, `original_increment_id`, `relation_child_id`, `relation_child_real_id`, `relation_parent_id`, `relation_parent_real_id`, `remote_ip`, `shipping_method`, `store_currency_code`, `store_name`, `x_forwarded_for`, `customer_note`, `created_at`, `updated_at`, `total_item_count`, `customer_gender`, `hidden_tax_amount`, `base_hidden_tax_amount`, `shipping_hidden_tax_amount`, `base_shipping_hidden_tax_amnt`, `hidden_tax_invoiced`, `base_hidden_tax_invoiced`, `hidden_tax_refunded`, `base_hidden_tax_refunded`, `shipping_incl_tax`, `base_shipping_incl_tax`, `coupon_rule_name`, `gift_message_id`) VALUES ({$salesOrderId}, 'new', 'pending', NULL, '272ecb', 'Flat Rate - Fixed', 0, {$productStoreId($entityId)}, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, 1.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2.0000, NULL, NULL, NULL, 1, 1, 2, 0, NULL, 1, 1, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, 17.0000, 25.3000, NULL, NULL, 17.0000, 25.3000, 2.0000, NULL, {$orderNumber}, '1', 'USD', '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'USD', NULL, NULL, 'USD', NULL, NULL, NULL, NULL, NULL, '127.0.0.1', 'flatrate_flatrate', 'USD', '{$productStoreName($entityId)}', NULL, NULL, '{$time}', '{$time}', 2, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL);"; + + $salesOrderAddressId[0] = $quoteAddressId[0]; + $salesOrderAddressId[1] = $quoteAddressId[1]; + $queries .= "INSERT INTO `{$salesOrderAddressTableName}` (`entity_id`, `parent_id`, `customer_address_id`, `quote_address_id`, `region_id`, `customer_id`, `fax`, `region`, `postcode`, `lastname`, `street`, `city`, `email`, `telephone`, `country_id`, `firstname`, `address_type`, `prefix`, `middlename`, `suffix`, `company`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`) VALUES ({$salesOrderAddressId[0]}, {$salesOrderId}, NULL, NULL, 1, NULL, NULL, '{$state}', '{$zip}', '{$lastName}', '{$address}', '{$city}', '{$email}', '{$phone}', '{$country}', '{$firstName}', 'shipping', NULL, NULL, NULL, '{$company}', NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$salesOrderAddressTableName}` (`entity_id`, `parent_id`, `customer_address_id`, `quote_address_id`, `region_id`, `customer_id`, `fax`, `region`, `postcode`, `lastname`, `street`, `city`, `email`, `telephone`, `country_id`, `firstname`, `address_type`, `prefix`, `middlename`, `suffix`, `company`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`) VALUES ({$salesOrderAddressId[1]}, {$salesOrderId}, NULL, NULL, 1, NULL, NULL, '{$state}', '{$zip}', '{$lastName}', '{$address}', '{$city}', '{$email}', '{$phone}', '{$country}', '{$firstName}', 'billing', NULL, NULL, NULL, '{$company}', NULL, NULL, NULL, NULL, NULL);"; + + $salesOrderGridId = $salesOrderId; + $queries .= "INSERT INTO `{$salesOrderGridTableName}` (`entity_id`, `status`, `store_id`, `store_name`, `customer_id`, `base_grand_total`, `base_total_paid`, `grand_total`, `total_paid`, `increment_id`, `base_currency_code`, `order_currency_code`, `shipping_name`, `billing_name`, `created_at`, `updated_at`) VALUES ({$salesOrderGridId}, 'pending', {$productStoreId($entityId)}, '{$productStoreName($entityId)}', NULL, 25.3000, NULL, 25.3000, NULL, {$orderNumber}, 'USD', 'USD', '', '', '{$time}', NULL);"; + + $salesOrderItemId[0] = $quoteItemId[0]; + $salesOrderItemId[1] = $quoteItemId[1]; + $salesOrderItemId[2] = $quoteItemId[2]; + $salesOrderItemId[3] = $quoteItemId[3]; + $queries .= "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `hidden_tax_invoiced`, `base_hidden_tax_invoiced`, `hidden_tax_refunded`, `base_hidden_tax_refunded`, `tax_canceled`, `hidden_tax_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[0]}, {$salesOrderId}, NULL, {$quoteItemId[0]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[0]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `hidden_tax_invoiced`, `base_hidden_tax_invoiced`, `hidden_tax_refunded`, `base_hidden_tax_refunded`, `tax_canceled`, `hidden_tax_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[1]}, {$salesOrderId}, NULL, {$quoteItemId[1]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[1]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + + $salesOrderPaymentId = $salesOrderId; + $queries .= "INSERT INTO `{$salesOrderPaymentTableName}` (`entity_id`, `parent_id`, `base_shipping_captured`, `shipping_captured`, `amount_refunded`, `base_amount_paid`, `amount_canceled`, `base_amount_authorized`, `base_amount_paid_online`, `base_amount_refunded_online`, `base_shipping_amount`, `shipping_amount`, `amount_paid`, `amount_authorized`, `base_amount_ordered`, `base_shipping_refunded`, `shipping_refunded`, `base_amount_refunded`, `amount_ordered`, `base_amount_canceled`, `quote_payment_id`, `additional_data`, `cc_exp_month`, `cc_ss_start_year`, `echeck_bank_name`, `method`, `cc_debug_request_body`, `cc_secure_verify`, `protection_eligibility`, `cc_approval`, `cc_last_4`, `cc_status_description`, `echeck_type`, `cc_debug_response_serialized`, `cc_ss_start_month`, `echeck_account_type`, `last_trans_id`, `cc_cid_status`, `cc_owner`, `cc_type`, `po_number`, `cc_exp_year`, `cc_status`, `echeck_routing_number`, `account_status`, `anet_trans_method`, `cc_debug_response_body`, `cc_ss_issue`, `echeck_account_name`, `cc_avs_status`, `cc_number_enc`, `cc_trans_id`, `address_status`, `additional_information`) VALUES ({$salesOrderPaymentId}, {$salesOrderId}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL, 25.3000, NULL, NULL, NULL, 25.3000, NULL, NULL, NULL, NULL, '0', NULL, 'checkmo', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'a:1:{s:53:\"a:1:{s:12:\"method_title\";s:19:\"Check / Money order\";}\";N;}');"; + + $salesOrderStatusHistoryId = $salesOrderId; + $queries .= "INSERT INTO `{$salesOrderStatusHistoryTableName}` (`entity_id`, `parent_id`, `is_customer_notified`, `is_visible_on_front`, `comment`, `status`, `created_at`, `entity_name`) VALUES ({$salesOrderStatusHistoryId}, {$salesOrderId}, 1, 0, NULL, 'pending', '{$time}', 'order');"; + + $writeAdapter->multiQuery($queries); + + $entityId++; + } + } + + /** + * {@inheritdoc} + */ + public function getActionTitle() + { + return 'Generating orders'; + } + + /** + * {@inheritdoc} + */ + public function introduceParamLabels() + { + return [ + 'orders' => 'Orders' + ]; + } + + /** + * Get real table name for db table, validated by db adapter + * + * @param string $tableName + * @param string $resourceName + * @return string + */ + public function getTableName($tableName, $resourceName) + { + $resource = $this->application->getObjectManager()->get($resourceName); + return $this->getConnection('write')->getTableName($resource->getTable($tableName)); + } + + /** + * Retrieve connection to resource specified by $resourceName + * + * @param string $resourceName + * @return \Magento\Framework\DB\Adapter\AdapterInterface|false + */ + public function getConnection($resourceName) + { + return $this->application->getObjectManager()->get( + 'Magento\Framework\App\Resource' + )->getConnection($resourceName); + } +} + +return new OrdersFixture($this); diff --git a/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php b/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php index 98f5dc5d5e07250fe7b427ca68286cb99c22ee35..aa91250b41fb3ce83f95c8d3df94e144c79a9bfb 100644 --- a/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php +++ b/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Api\Code\Generator; use Magento\Framework\Code\Generator\DefinedClasses; use Magento\Framework\Code\Generator\Io; use Magento\Framework\Api\SimpleDataObjectConverter; +use Magento\Framework\Api\Config\Converter; /** * Code generator for data object extensions. @@ -79,14 +80,15 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent protected function _getClassMethods() { $methods = []; - foreach ($this->getCustomAttributes() as $attributeName => $attributeType) { + foreach ($this->getCustomAttributes() as $attributeName => $attributeMetadata) { + $attributeType = $attributeMetadata[Converter::DATA_TYPE]; $propertyName = SimpleDataObjectConverter::snakeCaseToCamelCase($attributeName); $getterName = 'get' . ucfirst($propertyName); $setterName = 'set' . ucfirst($propertyName); $methods[] = [ 'name' => $getterName, 'body' => "return \$this->_get('{$attributeName}');", - 'docblock' => ['tags' => [['name' => 'return', 'description' => $attributeType]]], + 'docblock' => ['tags' => [['name' => 'return', 'description' => $attributeType . '|null']]], ]; $methods[] = [ 'name' => $setterName, @@ -150,11 +152,12 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent } $dataInterface = ltrim($this->getSourceClassName(), '\\'); if (isset($this->allCustomAttributes[$dataInterface])) { - foreach ($this->allCustomAttributes[$dataInterface] as $attributeName => $attributeType) { + foreach ($this->allCustomAttributes[$dataInterface] as $attributeName => $attributeMetadata) { + $attributeType = $attributeMetadata[Converter::DATA_TYPE]; if (strpos($attributeType, '\\') !== false) { /** Add preceding slash to class names, while leaving primitive types as is */ $attributeType = $this->_getFullyQualifiedClassName($attributeType); - $this->allCustomAttributes[$dataInterface][$attributeName] = + $this->allCustomAttributes[$dataInterface][$attributeName][Converter::DATA_TYPE] = $this->_getFullyQualifiedClassName($attributeType); } } diff --git a/lib/internal/Magento/Framework/Api/Config/Converter.php b/lib/internal/Magento/Framework/Api/Config/Converter.php index f21db3bbd9b224b1c29eaa36be3f6043dcdf4ae9..68914a98b5c77ab1bc452c90fc26dfbee64797d8 100644 --- a/lib/internal/Magento/Framework/Api/Config/Converter.php +++ b/lib/internal/Magento/Framework/Api/Config/Converter.php @@ -7,6 +7,9 @@ namespace Magento\Framework\Api\Config; class Converter implements \Magento\Framework\Config\ConverterInterface { + const RESOURCE_PERMISSIONS = "resourceRefs"; + const DATA_TYPE = "type"; + /** * Convert dom node tree to array * @@ -21,7 +24,7 @@ class Converter implements \Magento\Framework\Config\ConverterInterface } /** @var \DOMNodeList $types */ - $types = $source->getElementsByTagName('custom_attributes'); + $types = $source->getElementsByTagName('extension_attributes'); /** @var \DOMNode $type */ foreach ($types as $type) { $typeConfig = []; @@ -32,9 +35,22 @@ class Converter implements \Magento\Framework\Config\ConverterInterface $code = $attribute->getAttribute('code'); $codeType = $attribute->getAttribute('type'); - if ($code && $codeType) { - $typeConfig[$code] = $codeType; + $resourcesElement = $attribute->getElementsByTagName('resources')->item(0); + $resourceRefs = []; + if ($resourcesElement && $resourcesElement->nodeType === XML_ELEMENT_NODE) { + $singleResourceElements = $resourcesElement->getElementsByTagName('resource'); + foreach ($singleResourceElements as $element) { + if ($element->nodeType != XML_ELEMENT_NODE) { + continue; + } + $resourceRefs[] = $element->attributes->getNamedItem('ref')->nodeValue; + } } + + $typeConfig[$code] = [ + self::DATA_TYPE => $codeType, + self::RESOURCE_PERMISSIONS => $resourceRefs, + ]; } $output[$typeName] = $typeConfig; diff --git a/lib/internal/Magento/Framework/Api/Config/Reader.php b/lib/internal/Magento/Framework/Api/Config/Reader.php index 8cd1a8ac3293568553c30f0e126ab1ee61b78a38..6bc97c71c11563cfb46efeaaedf2ecd03fd3bf83 100644 --- a/lib/internal/Magento/Framework/Api/Config/Reader.php +++ b/lib/internal/Magento/Framework/Api/Config/Reader.php @@ -13,8 +13,8 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem * @var array */ protected $_idAttributes = [ - '/config/custom_attributes' => 'for', - '/config/custom_attributes/attribute' => 'code', + '/config/extension_attributes' => 'for', + '/config/extension_attributes/attribute' => 'code', ]; /** @@ -32,7 +32,7 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem \Magento\Framework\Api\Config\Converter $converter, \Magento\Framework\Api\Config\SchemaLocator $schemaLocator, \Magento\Framework\Config\ValidationStateInterface $validationState, - $fileName = 'data_object.xml', + $fileName = 'service_data_attributes.xml', $idAttributes = [], $domDocumentClass = 'Magento\Framework\Config\Dom', $defaultScope = 'global' diff --git a/lib/internal/Magento/Framework/Api/Config/SchemaLocator.php b/lib/internal/Magento/Framework/Api/Config/SchemaLocator.php index 86662ab2528136ecc4c8182d650a55b9e80f0a2f..1e8334c643def347b9392eba52d624b5fdaab556 100644 --- a/lib/internal/Magento/Framework/Api/Config/SchemaLocator.php +++ b/lib/internal/Magento/Framework/Api/Config/SchemaLocator.php @@ -16,7 +16,7 @@ class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface */ public function getSchema() { - return realpath(__DIR__ . '/../etc/data_object.xsd'); + return realpath(__DIR__ . '/../etc/service_data_attributes.xsd'); } /** diff --git a/lib/internal/Magento/Framework/Api/DataObjectHelper.php b/lib/internal/Magento/Framework/Api/DataObjectHelper.php index d0a22a194be444bbc4b71f5d60dd6bf29fd1de42..fc3a3b0920c60430f28de95db7cd6a6ab84f6868 100644 --- a/lib/internal/Magento/Framework/Api/DataObjectHelper.php +++ b/lib/internal/Magento/Framework/Api/DataObjectHelper.php @@ -6,6 +6,8 @@ namespace Magento\Framework\Api; +use Magento\Framework\Reflection\MethodsMap; + class DataObjectHelper { /** @@ -28,22 +30,30 @@ class DataObjectHelper */ protected $extensionFactory; + /** + * @var MethodsMap + */ + protected $methodsMapProcessor; + /** * @param ObjectFactory $objectFactory * @param \Magento\Framework\Reflection\DataObjectProcessor $objectProcessor * @param \Magento\Framework\Reflection\TypeProcessor $typeProcessor * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory + * @param MethodsMap $methodsMapProcessor */ public function __construct( ObjectFactory $objectFactory, \Magento\Framework\Reflection\DataObjectProcessor $objectProcessor, \Magento\Framework\Reflection\TypeProcessor $typeProcessor, - \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory + \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, + MethodsMap $methodsMapProcessor ) { $this->objectFactory = $objectFactory; $this->objectProcessor = $objectProcessor; $this->typeProcessor = $typeProcessor; $this->extensionFactory = $extensionFactory; + $this->methodsMapProcessor = $methodsMapProcessor; } /** @@ -128,7 +138,7 @@ class DataObjectHelper if ($interfaceName == null) { $interfaceName = get_class($dataObject); } - $returnType = $this->objectProcessor->getMethodReturnType($interfaceName, $getterMethodName); + $returnType = $this->methodsMapProcessor->getMethodReturnType($interfaceName, $getterMethodName); if ($this->typeProcessor->isTypeSimple($returnType)) { $dataObject->$methodName($value); return $this; diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php index 5207a20588c73dcbf83aa767b907f585db8bb114..efdeb4ae914348fa51302891271d018b06c70067 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php @@ -6,6 +6,8 @@ // @codingStandardsIgnoreFile namespace Magento\Framework\Api\Test\Unit\Code\Generator; +use Magento\Framework\Api\Config\Converter; + class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase { /** @@ -44,11 +46,21 @@ class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase ->willReturn( [ 'Magento\Catalog\Api\Data\ProductInterface' => [ - 'string_attribute' => 'string', - 'complex_object_attribute' => '\Magento\Bundle\Api\Data\OptionInterface[]' + 'string_attribute' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + + ], + 'complex_object_attribute' => [ + Converter::DATA_TYPE => '\Magento\Bundle\Api\Data\OptionInterface[]', + Converter::RESOURCE_PERMISSIONS => [], + ], ], 'Magento\Catalog\Api\Data\Product' => [ - 'should_not_include' => 'string', + 'should_not_include' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + ], ], ] ); diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php index 8f80baf39beeeec1955800e7ea4a51ac12d02382..33d4ecf9e7906c2abd4bfe15ef429c539405b059 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php @@ -6,6 +6,8 @@ // @codingStandardsIgnoreFile namespace Magento\Framework\Api\Test\Unit\Code\Generator; +use Magento\Framework\Api\Config\Converter; + class ExtensionAttributesInterfaceGeneratorTest extends \PHPUnit_Framework_TestCase { public function testGenerate() @@ -19,11 +21,20 @@ class ExtensionAttributesInterfaceGeneratorTest extends \PHPUnit_Framework_TestC ->willReturn( [ 'Magento\Catalog\Api\Data\ProductInterface' => [ - 'string_attribute' => 'string', - 'complex_object_attribute' => '\Magento\Bundle\Api\Data\OptionInterface[]' + 'string_attribute' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + ], + 'complex_object_attribute' => [ + Converter::DATA_TYPE => '\Magento\Bundle\Api\Data\OptionInterface[]', + Converter::RESOURCE_PERMISSIONS => [], + ], ], 'Magento\Catalog\Api\Data\Product' => [ - 'should_not_include' => 'string', + 'should_not_include' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + ], ], ] ); diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtension.txt b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtension.txt index 8b5caad1ecc4456ae51380e25c735be8f2660d37..0f9838bd8736c9c0545b6bb82ab5adbe9762a946 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtension.txt +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtension.txt @@ -6,7 +6,7 @@ namespace Magento\Catalog\Api\Data; class ProductExtension extends \Magento\Framework\Api\AbstractSimpleObject implements \Magento\Catalog\Api\Data\ProductExtensionInterface { /** - * @return string + * @return string|null */ public function getStringAttribute() { @@ -24,7 +24,7 @@ class ProductExtension extends \Magento\Framework\Api\AbstractSimpleObject imple } /** - * @return \Magento\Bundle\Api\Data\OptionInterface[] + * @return \Magento\Bundle\Api\Data\OptionInterface[]|null */ public function getComplexObjectAttribute() { diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtensionInterface.txt b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtensionInterface.txt index ec9edd7affc2d68e5444d914b833bff81ccc1d4d..75dde39b2151952b49beb587ce4eecff56418997 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtensionInterface.txt +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/_files/SampleExtensionInterface.txt @@ -6,7 +6,7 @@ namespace Magento\Catalog\Api\Data; interface ProductExtensionInterface extends \Magento\Framework\Api\ExtensionAttributesInterface { /** - * @return string + * @return string|null */ public function getStringAttribute(); @@ -17,7 +17,7 @@ interface ProductExtensionInterface extends \Magento\Framework\Api\ExtensionAttr public function setStringAttribute($stringAttribute); /** - * @return \Magento\Bundle\Api\Data\OptionInterface[] + * @return \Magento\Bundle\Api\Data\OptionInterface[]|null */ public function getComplexObjectAttribute(); diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/ConverterTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Config/ConverterTest.php index 94f5a4494a75dd9c57afa409c90eb622ad26827c..d4629213b20be2d7bbca2ff16bacf0b36de608e5 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Config/ConverterTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Config/ConverterTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\Api\Test\Unit\Config; +use Magento\Framework\Api\Config\Converter; + class ConverterTest extends \PHPUnit_Framework_TestCase { /** @@ -47,15 +49,39 @@ class ConverterTest extends \PHPUnit_Framework_TestCase 'Magento\Tax\Api\Data\TaxRateInterface' => [ ], 'Magento\Catalog\Api\Data\ProductInterface' => [ - 'stock_item' => 'Magento\CatalogInventory\Api\Data\StockItemInterface' + 'stock_item' => [ + Converter::DATA_TYPE => 'Magento\CatalogInventory\Api\Data\StockItemInterface', + Converter::RESOURCE_PERMISSIONS => [], + ], ], 'Magento\Customer\Api\Data\CustomerInterface' => [ - 'custom_1' => 'Magento\Customer\Api\Data\CustomerCustom', - 'custom_2' => 'Magento\CustomerExtra\Api\Data\CustomerCustom2' + 'custom_1' => [ + Converter::DATA_TYPE => 'Magento\Customer\Api\Data\CustomerCustom', + Converter::RESOURCE_PERMISSIONS => [], + ], + 'custom_2' => [ + Converter::DATA_TYPE => 'Magento\CustomerExtra\Api\Data\CustomerCustom2', + Converter::RESOURCE_PERMISSIONS => [], + ], + ], + 'Magento\Customer\Api\Data\CustomerInterface2' => [ + 'custom_with_permission' => [ + Converter::DATA_TYPE => 'Magento\Customer\Api\Data\CustomerCustom', + Converter::RESOURCE_PERMISSIONS => [ + 'Magento_Customer::manage', + ], + ], + 'custom_with_multiple_permissions' => [ + Converter::DATA_TYPE => 'Magento\CustomerExtra\Api\Data\CustomerCustom2', + Converter::RESOURCE_PERMISSIONS => [ + 'Magento_Customer::manage', + 'Magento_Customer::manage2', + ], + ], ], ]; - $xmlFile = __DIR__ . '/_files/data_object_valid.xml'; + $xmlFile = __DIR__ . '/_files/service_data_attributes.xml'; $dom = new \DOMDocument(); $dom->loadXML(file_get_contents($xmlFile)); $result = $this->_converter->convert($dom); diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/SchemaLocatorTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Config/SchemaLocatorTest.php index f0df38d59a070958d77d6ddccb0d339162d256da..f05583db0490194e949261bce0a2c176932dbdb5 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Config/SchemaLocatorTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Config/SchemaLocatorTest.php @@ -22,7 +22,7 @@ class SchemaLocatorTest extends \PHPUnit_Framework_TestCase public function testGetSchema() { - $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/data_object.xsd'); + $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd'); $actual = str_replace('\\', '/', $this->_model->getSchema()); $this->assertEquals($expected, $actual); } @@ -30,7 +30,7 @@ class SchemaLocatorTest extends \PHPUnit_Framework_TestCase public function testGetPerFileSchema() { $actual = str_replace('\\', '/', $this->_model->getPerFileSchema()); - $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/data_object.xsd'); + $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd'); $this->assertEquals($expected, $actual); } } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/data_object_valid.xml b/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/data_object_valid.xml deleted file mode 100644 index 67606deab2eb46e78dc3022a723b41a1bb25bfa3..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/data_object_valid.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd"> - <custom_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> - </custom_attributes> - <custom_attributes for="Magento\Catalog\Api\Data\ProductInterface"> - <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface" /> - </custom_attributes> - <custom_attributes for="Magento\Customer\Api\Data\CustomerInterface"> - <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom" /> - <attribute code="custom_2" type="Magento\CustomerExtra\Api\Data\CustomerCustom2" /> - </custom_attributes> -</config> diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/service_data_attributes.xml b/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/service_data_attributes.xml new file mode 100644 index 0000000000000000000000000000000000000000..4f6a9838bfcdb6bd9dbfa20b18ffcfde80bd625d --- /dev/null +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/service_data_attributes.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + </extension_attributes> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> + <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface" /> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> + <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom" /> + <attribute code="custom_2" type="Magento\CustomerExtra\Api\Data\CustomerCustom2" /> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface2"> + <attribute code="custom_with_permission" type="Magento\Customer\Api\Data\CustomerCustom"> + <resources> + <resource ref="Magento_Customer::manage"/> + </resources> + </attribute> + <attribute code="custom_with_multiple_permissions" type="Magento\CustomerExtra\Api\Data\CustomerCustom2"> + <resources> + <resource ref="Magento_Customer::manage"/> + <resource ref="Magento_Customer::manage2"/> + </resources> + </attribute> + </extension_attributes> +</config> diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php index ff229abd7d22e9be0f810da4034336e5e9631f63..65c7cb906d1f2f15b8f251145633cdb6e85848c5 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php @@ -43,6 +43,11 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase */ protected $attributeValueFactoryMock; + /** + * @var \Magento\Framework\Reflection\MethodsMap|\PHPUnit_Framework_MockObject_MockObject + */ + protected $methodsMapProcessor; + public function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -53,6 +58,9 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase $this->objectProcessorMock = $this->getMockBuilder('\Magento\Framework\Reflection\DataObjectProcessor') ->disableOriginalConstructor() ->getMock(); + $this->methodsMapProcessor = $this->getMockBuilder('\Magento\Framework\Reflection\MethodsMap') + ->disableOriginalConstructor() + ->getMock(); $this->attributeValueFactoryMock = $this->getMockBuilder('\Magento\Framework\Api\AttributeValueFactory') ->disableOriginalConstructor() ->getMock(); @@ -63,6 +71,7 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase 'objectFactory' => $this->objectFactoryMock, 'typeProcessor' => $this->typeProcessor, 'objectProcessor' => $this->objectProcessorMock, + 'methodsMapProcessor' => $this->methodsMapProcessor, ] ); } @@ -103,11 +112,11 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase ], ]; - $this->objectProcessorMock->expects($this->at(0)) + $this->methodsMapProcessor->expects($this->at(0)) ->method('getMethodReturnType') ->with('\Magento\Customer\Api\Data\AddressInterface', 'getStreet') ->willReturn('string[]'); - $this->objectProcessorMock->expects($this->at(1)) + $this->methodsMapProcessor->expects($this->at(1)) ->method('getMethodReturnType') ->with('\Magento\Customer\Api\Data\AddressInterface', 'getRegion') ->willReturn('\Magento\Customer\Api\Data\RegionInterface'); @@ -317,11 +326,11 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase ->method('buildOutputDataArray') ->with($secondAddressDataObject, get_class($firstAddressDataObject)) ->willReturn($data2); - $this->objectProcessorMock->expects($this->at(1)) + $this->methodsMapProcessor->expects($this->at(0)) ->method('getMethodReturnType') ->with('Magento\Customer\Model\Data\Address', 'getStreet') ->willReturn('string[]'); - $this->objectProcessorMock->expects($this->at(2)) + $this->methodsMapProcessor->expects($this->at(1)) ->method('getMethodReturnType') ->with('Magento\Customer\Model\Data\Address', 'getRegion') ->willReturn('\Magento\Customer\Api\Data\RegionInterface'); diff --git a/lib/internal/Magento/Framework/Api/etc/data_object.xsd b/lib/internal/Magento/Framework/Api/etc/data_object.xsd deleted file mode 100644 index 0983dbbf912385c5a83dd1b8db18d768071c42fc..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/Api/etc/data_object.xsd +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="config"> - <xs:complexType> - <xs:sequence> - <xs:element name="custom_attributes" type="custom_attributesType" minOccurs="1" maxOccurs="unbounded"> - <xs:annotation> - <xs:documentation>Main schema element. Extended Attributes</xs:documentation> - </xs:annotation> - </xs:element> - </xs:sequence> - </xs:complexType> - </xs:element> - <xs:complexType name="attributeType"> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute type="xs:string" name="code" use="required"/> - <xs:attribute type="xs:string" name="type" use="required"/> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - <xs:complexType name="custom_attributesType"> - <xs:sequence> - <xs:element type="attributeType" name="attribute" minOccurs="0" maxOccurs="unbounded"/> - </xs:sequence> - <xs:attribute type="xs:string" name="for" use="required"/> - </xs:complexType> -</xs:schema> diff --git a/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd b/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd new file mode 100644 index 0000000000000000000000000000000000000000..24590e3d758c79afeef7ce85c8cb9f6547e6f524 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="config"> + <xs:complexType> + <xs:sequence> + <xs:element name="extension_attributes" type="extension_attributesType" minOccurs="1" + maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Main schema element. Extended Attributes</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:complexType name="attributeType"> + <xs:sequence> + <xs:element name="resources" type="resourcesType" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute type="xs:string" name="code" use="required"/> + <xs:attribute type="xs:string" name="type" use="required"/> + </xs:complexType> + <xs:complexType name="extension_attributesType"> + <xs:sequence> + <xs:element type="attributeType" name="attribute" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute type="xs:string" name="for" use="required"/> + </xs:complexType> + <xs:complexType name="resourcesType"> + <xs:sequence> + <xs:element name="resource" type="resourceType" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="resourceType"> + <xs:attribute name="ref" use="required"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:pattern value=".+(, ?.+)*"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> +</xs:schema> diff --git a/lib/internal/Magento/Framework/App/Action/AbstractAction.php b/lib/internal/Magento/Framework/App/Action/AbstractAction.php index b0027ca824ec085480664fcbfe0ce6d36e0c60bd..d6119f9fe876b972e7a7513050c4af994d95bf53 100644 --- a/lib/internal/Magento/Framework/App/Action/AbstractAction.php +++ b/lib/internal/Magento/Framework/App/Action/AbstractAction.php @@ -24,6 +24,11 @@ abstract class AbstractAction implements \Magento\Framework\App\ActionInterface */ protected $resultRedirectFactory; + /** + * @var \Magento\Framework\Controller\ResultFactory + */ + protected $resultFactory; + /** * @param \Magento\Framework\App\Action\Context $context */ @@ -33,6 +38,7 @@ abstract class AbstractAction implements \Magento\Framework\App\ActionInterface $this->_request = $context->getRequest(); $this->_response = $context->getResponse(); $this->resultRedirectFactory = $context->getResultRedirectFactory(); + $this->resultFactory = $context->getResultFactory(); } /** diff --git a/lib/internal/Magento/Framework/App/Action/Context.php b/lib/internal/Magento/Framework/App/Action/Context.php index 22aef5cc083c9dd8278100b6afcd6fffc6858884..a812800bc059948ac5b0cdd85eb04f7891445379 100644 --- a/lib/internal/Magento/Framework/App/Action/Context.php +++ b/lib/internal/Magento/Framework/App/Action/Context.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\App\Action; +use Magento\Framework\Controller\ResultFactory; + class Context implements \Magento\Framework\ObjectManager\ContextInterface { /** @@ -57,6 +59,11 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface */ protected $resultRedirectFactory; + /** + * @var \Magento\Framework\Controller\ResultFactory + */ + protected $resultFactory; + /** * @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Framework\App\ResponseInterface $response @@ -68,6 +75,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface * @param \Magento\Framework\App\ViewInterface $view * @param \Magento\Framework\Message\ManagerInterface $messageManager * @param \Magento\Framework\Controller\Result\RedirectFactory $resultRedirectFactory + * @param \Magento\Framework\Controller\ResultFactory $resultFactory * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -81,7 +89,8 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface \Magento\Framework\App\ActionFlag $actionFlag, \Magento\Framework\App\ViewInterface $view, \Magento\Framework\Message\ManagerInterface $messageManager, - \Magento\Framework\Controller\Result\RedirectFactory $resultRedirectFactory + \Magento\Framework\Controller\Result\RedirectFactory $resultRedirectFactory, + ResultFactory $resultFactory ) { $this->_request = $request; $this->_response = $response; @@ -93,6 +102,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface $this->_view = $view; $this->messageManager = $messageManager; $this->resultRedirectFactory = $resultRedirectFactory; + $this->resultFactory = $resultFactory; } /** @@ -174,4 +184,12 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface { return $this->resultRedirectFactory; } + + /** + * @return \Magento\Framework\Controller\ResultFactory + */ + public function getResultFactory() + { + return $this->resultFactory; + } } diff --git a/lib/internal/Magento/Framework/App/Area/FrontNameResolverInterface.php b/lib/internal/Magento/Framework/App/Area/FrontNameResolverInterface.php index bbdd3787b1825ffa9c35882776a9173c03b9607a..e8a3e92263e7d9b50226911e4d445b1a663171f7 100644 --- a/lib/internal/Magento/Framework/App/Area/FrontNameResolverInterface.php +++ b/lib/internal/Magento/Framework/App/Area/FrontNameResolverInterface.php @@ -7,6 +7,10 @@ */ namespace Magento\Framework\App\Area; +/** + * Interface FrontNameResolverInterface + * @api + */ interface FrontNameResolverInterface { /** diff --git a/lib/internal/Magento/Framework/App/AreaInterface.php b/lib/internal/Magento/Framework/App/AreaInterface.php index 806a7983424599690e3b7f02443fb7e9b4b328a5..544ac56e19e6f10dd13c5a284d56dba2d6e4b010 100644 --- a/lib/internal/Magento/Framework/App/AreaInterface.php +++ b/lib/internal/Magento/Framework/App/AreaInterface.php @@ -6,6 +6,9 @@ */ namespace Magento\Framework\App; +/** + * Interface AreaInterface + */ interface AreaInterface { const PART_CONFIG = 'config'; diff --git a/lib/internal/Magento/Framework/App/AreaList.php b/lib/internal/Magento/Framework/App/AreaList.php index 270fb22e36675b08576b06500e7cd6da38f39466..c010388797d870fa25e7aec9a192edef8ed0a73b 100644 --- a/lib/internal/Magento/Framework/App/AreaList.php +++ b/lib/internal/Magento/Framework/App/AreaList.php @@ -63,6 +63,7 @@ class AreaList * * @param string $frontName * @return null|string + * @api */ public function getCodeByFrontName($frontName) { @@ -84,6 +85,7 @@ class AreaList * * @param string $areaCode * @return string + * @api */ public function getFrontName($areaCode) { @@ -94,6 +96,7 @@ class AreaList * Retrieve area codes * * @return string[] + * @api */ public function getCodes() { @@ -105,6 +108,7 @@ class AreaList * * @param string $areaCode * @return string + * @api */ public function getDefaultRouter($areaCode) { diff --git a/lib/internal/Magento/Framework/App/Cache/Type/Config.php b/lib/internal/Magento/Framework/App/Cache/Type/Config.php index ded73329969b9f7faec6409ed73715cab06390eb..506eff32a8e099edc9a4a9193b7e42bafdc2ac58 100644 --- a/lib/internal/Magento/Framework/App/Cache/Type/Config.php +++ b/lib/internal/Magento/Framework/App/Cache/Type/Config.php @@ -25,10 +25,40 @@ class Config extends TagScope implements CacheInterface const CACHE_TAG = 'CONFIG'; /** - * @param FrontendPool $cacheFrontendPool + * @var \Magento\Framework\App\Cache\Type\FrontendPool */ - public function __construct(FrontendPool $cacheFrontendPool) + private $cacheFrontendPool; + + /** + * @param \Magento\Framework\App\Cache\Type\FrontendPool $cacheFrontendPool + */ + public function __construct(\Magento\Framework\App\Cache\Type\FrontendPool $cacheFrontendPool) + { + $this->cacheFrontendPool = $cacheFrontendPool; + } + + /** + * Retrieve cache frontend instance being decorated + * + * @return \Magento\Framework\Cache\FrontendInterface + */ + protected function _getFrontend() + { + $frontend = parent::_getFrontend(); + if (!$frontend) { + $frontend = $this->cacheFrontendPool->get(self::TYPE_IDENTIFIER); + $this->setFrontend($frontend); + } + return $frontend; + } + + /** + * Retrieve cache tag name + * + * @return string + */ + public function getTag() { - parent::__construct($cacheFrontendPool->get(self::TYPE_IDENTIFIER), self::CACHE_TAG); + return self::CACHE_TAG; } } diff --git a/lib/internal/Magento/Framework/App/Config.php b/lib/internal/Magento/Framework/App/Config.php index 047849f0034bde6164c2a054c81817e2daccdd2a..898a19a00ea5f20ff98bce5a7cb5eaa322972869 100644 --- a/lib/internal/Magento/Framework/App/Config.php +++ b/lib/internal/Magento/Framework/App/Config.php @@ -7,6 +7,8 @@ */ namespace Magento\Framework\App; +use Magento\Framework\App\Config\ScopeConfigInterface; + class Config implements \Magento\Framework\App\Config\ScopeConfigInterface { /** @@ -37,7 +39,7 @@ class Config implements \Magento\Framework\App\Config\ScopeConfigInterface */ public function getValue( $path = null, - $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null ) { return $this->_scopePool->getScope($scope, $scopeCode)->getValue($path); @@ -51,7 +53,7 @@ class Config implements \Magento\Framework\App\Config\ScopeConfigInterface * @param null|string $scopeCode * @return bool */ - public function isSetFlag($path, $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $scopeCode = null) + public function isSetFlag($path, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) { return (bool) $this->getValue($path, $scope, $scopeCode); } diff --git a/lib/internal/Magento/Framework/App/Config/Data.php b/lib/internal/Magento/Framework/App/Config/Data.php index 3b5f17fe71639559575a77bc431fccc7071388f0..38389e71e40aaf297d4983bdde8377db615d5493 100644 --- a/lib/internal/Magento/Framework/App/Config/Data.php +++ b/lib/internal/Magento/Framework/App/Config/Data.php @@ -42,10 +42,7 @@ class Data implements DataInterface } /** - * Retrieve configuration value by path - * - * @param null|string $path - * @return array|string + * @inheritdoc */ public function getValue($path = null) { @@ -65,11 +62,7 @@ class Data implements DataInterface } /** - * Set configuration value - * - * @param string $path - * @param mixed $value - * @return void + * @inheritdoc */ public function setValue($path, $value) { diff --git a/lib/internal/Magento/Framework/App/Config/Data/ProcessorFactory.php b/lib/internal/Magento/Framework/App/Config/Data/ProcessorFactory.php index 8f473e2a37b2ba3c9cf3a0e707dd43f9bbe70902..8084dcd5d08f45c755a9c5b0490bf1fea78f8894 100644 --- a/lib/internal/Magento/Framework/App/Config/Data/ProcessorFactory.php +++ b/lib/internal/Magento/Framework/App/Config/Data/ProcessorFactory.php @@ -30,21 +30,22 @@ class ProcessorFactory /** * Get concrete Processor Interface instance * - * @param string $model + * @param string $processorModel Classname of the instance to get * @return ProcessorInterface - * @throws \InvalidArgumentException + * @throws \InvalidArgumentException In case the given classname is not an instance of ProcessorInterface + * @api */ - public function get($model) + public function get($processorModel) { - if (!isset($this->_pool[$model])) { - $instance = $this->_objectManager->create($model); + if (!isset($this->_pool[$processorModel])) { + $instance = $this->_objectManager->create($processorModel); if (!$instance instanceof ProcessorInterface) { throw new \InvalidArgumentException( - $model . ' is not instance of \Magento\Framework\App\Config\Data\ProcessorInterface' + $processorModel . ' is not instance of \Magento\Framework\App\Config\Data\ProcessorInterface' ); } - $this->_pool[$model] = $instance; + $this->_pool[$processorModel] = $instance; } - return $this->_pool[$model]; + return $this->_pool[$processorModel]; } } diff --git a/lib/internal/Magento/Framework/App/Config/Data/ProcessorInterface.php b/lib/internal/Magento/Framework/App/Config/Data/ProcessorInterface.php index 71102131f42cf4071b6d213d225ac8178956945a..d4467339676739d2e92250b986d992458772cc68 100644 --- a/lib/internal/Magento/Framework/App/Config/Data/ProcessorInterface.php +++ b/lib/internal/Magento/Framework/App/Config/Data/ProcessorInterface.php @@ -1,19 +1,22 @@ <?php /** - * Processor interface - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\App\Config\Data; +/** + * Processes data from admin store configuration fields + * + * @api + */ interface ProcessorInterface { /** * Process config value * - * @param string $value - * @return string + * @param string $value Raw value of the configuration field + * @return string Processed value */ public function processValue($value); } diff --git a/lib/internal/Magento/Framework/App/Config/DataInterface.php b/lib/internal/Magento/Framework/App/Config/DataInterface.php index bbdaf54d1c342a11803527f92160ebacef27a0a6..b07ca0e0df1fc3ce8085227057148619c371f0f9 100644 --- a/lib/internal/Magento/Framework/App/Config/DataInterface.php +++ b/lib/internal/Magento/Framework/App/Config/DataInterface.php @@ -5,11 +5,27 @@ */ namespace Magento\Framework\App\Config; +/** + * Configuration data storage + * + * @api + */ interface DataInterface { /** + * Retrieve configuration value by path + * * @param string|null $path - * @return string|array + * @return mixed */ public function getValue($path); + + /** + * Set configuration value by path + * + * @param string $path + * @param mixed $value + * @return void + */ + public function setValue($path, $value); } diff --git a/lib/internal/Magento/Framework/App/Config/Initial.php b/lib/internal/Magento/Framework/App/Config/Initial.php index 68db7b1eb84d42c669f3874b180038292a087983..3b2beb5ca37423ee054d94d2d3289bdacd21bca5 100644 --- a/lib/internal/Magento/Framework/App/Config/Initial.php +++ b/lib/internal/Magento/Framework/App/Config/Initial.php @@ -7,6 +7,8 @@ */ namespace Magento\Framework\App\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; + class Initial { /** @@ -50,14 +52,14 @@ class Initial /** * Get initial data by given scope * - * @param string $scope + * @param string $scope Format is scope type and scope code separated by pipe: e.g. "type|code" * @return array */ public function getData($scope) { list($scopeType, $scopeCode) = array_pad(explode('|', $scope), 2, null); - if (\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT == $scopeType) { + if (ScopeConfigInterface::SCOPE_TYPE_DEFAULT == $scopeType) { return isset($this->_data[$scopeType]) ? $this->_data[$scopeType] : []; } elseif ($scopeCode) { return isset($this->_data[$scopeType][$scopeCode]) ? $this->_data[$scopeType][$scopeCode] : []; diff --git a/lib/internal/Magento/Framework/App/Config/MutableScopeConfigInterface.php b/lib/internal/Magento/Framework/App/Config/MutableScopeConfigInterface.php index 37a371b547f40439addcfad205d29dd9c178fb07..f68048ddc94611267e17df9c85eb203bf28097a2 100644 --- a/lib/internal/Magento/Framework/App/Config/MutableScopeConfigInterface.php +++ b/lib/internal/Magento/Framework/App/Config/MutableScopeConfigInterface.php @@ -8,6 +8,9 @@ namespace Magento\Framework\App\Config; +/** + * @api + */ interface MutableScopeConfigInterface extends \Magento\Framework\App\Config\ScopeConfigInterface { /** @@ -15,14 +18,14 @@ interface MutableScopeConfigInterface extends \Magento\Framework\App\Config\Scop * * @param string $path * @param mixed $value - * @param string $scope + * @param string $scopeType * @param null|string $scopeCode * @return void */ public function setValue( $path, $value, - $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + $scopeType = \Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null ); } diff --git a/lib/internal/Magento/Framework/App/Config/ReinitableConfigInterface.php b/lib/internal/Magento/Framework/App/Config/ReinitableConfigInterface.php index 5b9d9d78eb3b4789a2ac6477e5e686ff3e4f0c6f..f9fc887a878e0ec0b73e2ad956ae0ff3b1ae166a 100644 --- a/lib/internal/Magento/Framework/App/Config/ReinitableConfigInterface.php +++ b/lib/internal/Magento/Framework/App/Config/ReinitableConfigInterface.php @@ -8,6 +8,9 @@ namespace Magento\Framework\App\Config; +/** + * @api + */ interface ReinitableConfigInterface extends \Magento\Framework\App\Config\MutableScopeConfigInterface { /** diff --git a/lib/internal/Magento/Framework/App/Config/Resource/ConfigInterface.php b/lib/internal/Magento/Framework/App/Config/Resource/ConfigInterface.php index aa0e06048980767a44d1f0688ebe6956bbb13355..8084c21ab0d9cd26be2319dd9cfad4e00992dae7 100644 --- a/lib/internal/Magento/Framework/App/Config/Resource/ConfigInterface.php +++ b/lib/internal/Magento/Framework/App/Config/Resource/ConfigInterface.php @@ -6,12 +6,12 @@ namespace Magento\Framework\App\Config\Resource; /** - * Resource Config Interface + * Resource for storing store configuration values */ interface ConfigInterface { /** - * Save config value + * Save config value to the storage resource * * @param string $path * @param string $value @@ -22,7 +22,7 @@ interface ConfigInterface public function saveConfig($path, $value, $scope, $scopeId); /** - * Delete config value + * Delete config value from the storage resource * * @param string $path * @param string $scope diff --git a/lib/internal/Magento/Framework/App/Config/Scope/ReaderInterface.php b/lib/internal/Magento/Framework/App/Config/Scope/ReaderInterface.php index bf20ecd1d530881e76749275afcff6dbd87939d1..cdcbb42828e51d4ff2f3e13c9449037c64ac9ad5 100644 --- a/lib/internal/Magento/Framework/App/Config/Scope/ReaderInterface.php +++ b/lib/internal/Magento/Framework/App/Config/Scope/ReaderInterface.php @@ -12,7 +12,9 @@ interface ReaderInterface /** * Read configuration scope * + * @param string|null $scopeType + * @throws \Exception May throw an exception if the given scope is invalid * @return array */ - public function read(); + public function read($scopeType = null); } diff --git a/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php b/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php index ac84e7358b5d2599a531ea45047d92626370bd44..e98fe284024f1780d731500d810516011b7528ba 100644 --- a/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php +++ b/lib/internal/Magento/Framework/App/Config/ScopeConfigInterface.php @@ -8,25 +8,33 @@ namespace Magento\Framework\App\Config; +/** + * @api + */ interface ScopeConfigInterface { /** - * Retrieve config value by path and scope + * Default scope type + */ + const SCOPE_TYPE_DEFAULT = 'default'; + + /** + * Retrieve config value by path and scope. * - * @param string $path - * @param string $scope + * @param string $path The path through the tree of configuration values, e.g., 'general/store_information/name' + * @param string $scopeType The scope to use to determine config value, e.g., 'store' or 'default' * @param null|string $scopeCode * @return mixed */ - public function getValue($path, $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $scopeCode = null); + public function getValue($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null); /** * Retrieve config flag by path and scope * - * @param string $path - * @param string $scope + * @param string $path The path through the tree of configuration values, e.g., 'general/store_information/name' + * @param string $scopeType The scope to use to determine config value, e.g., 'store' or 'default' * @param null|string $scopeCode * @return bool */ - public function isSetFlag($path, $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $scopeCode = null); + public function isSetFlag($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null); } diff --git a/lib/internal/Magento/Framework/App/Config/ScopePool.php b/lib/internal/Magento/Framework/App/Config/ScopePool.php index 34b24deb0028b63402dc2d169f2dbb47566dae9d..1a15575b1a514a0a0a04b728e454c2c18ef0645e 100644 --- a/lib/internal/Magento/Framework/App/Config/ScopePool.php +++ b/lib/internal/Magento/Framework/App/Config/ScopePool.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\App\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; + class ScopePool { const CACHE_TAG = 'config_scopes'; @@ -78,7 +80,7 @@ class ScopePool $data = unserialize($data); } else { $reader = $this->_readerPool->getReader($scopeType); - if ($scopeType === \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT) { + if ($scopeType === ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { $data = $reader->read(); } else { $data = $reader->read($scopeCode); @@ -111,7 +113,7 @@ class ScopePool protected function _getScopeCode($scopeType, $scopeCode) { if (($scopeCode === null || is_numeric($scopeCode)) - && $scopeType !== \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + && $scopeType !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT ) { $scopeResolver = $this->_scopeResolverPool->get($scopeType); $scopeCode = $scopeResolver->getScope($scopeCode); diff --git a/lib/internal/Magento/Framework/App/Config/Storage/Writer.php b/lib/internal/Magento/Framework/App/Config/Storage/Writer.php index b98e4074efa1b953fac38e02be2bbe435568d8c5..63b5ae83dfec68c85f61ebf17ae11396b485373e 100644 --- a/lib/internal/Magento/Framework/App/Config/Storage/Writer.php +++ b/lib/internal/Magento/Framework/App/Config/Storage/Writer.php @@ -7,6 +7,8 @@ */ namespace Magento\Framework\App\Config\Storage; +use Magento\Framework\App\Config\ScopeConfigInterface; + class Writer implements \Magento\Framework\App\Config\Storage\WriterInterface { /** @@ -32,7 +34,7 @@ class Writer implements \Magento\Framework\App\Config\Storage\WriterInterface * @param int $scopeId * @return void */ - public function delete($path, $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $scopeId = 0) + public function delete($path, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeId = 0) { $this->_resource->deleteConfig(rtrim($path, '/'), $scope, $scopeId); } @@ -46,7 +48,7 @@ class Writer implements \Magento\Framework\App\Config\Storage\WriterInterface * @param int $scopeId * @return void */ - public function save($path, $value, $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $scopeId = 0) + public function save($path, $value, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeId = 0) { $this->_resource->saveConfig(rtrim($path, '/'), $value, $scope, $scopeId); } diff --git a/lib/internal/Magento/Framework/App/Config/Storage/WriterInterface.php b/lib/internal/Magento/Framework/App/Config/Storage/WriterInterface.php index 3a3a3af6241361ca757699bf1d1e37ecfab6ad45..67b2aebd5d4a6da8d19eaad74175ca26726a57e0 100644 --- a/lib/internal/Magento/Framework/App/Config/Storage/WriterInterface.php +++ b/lib/internal/Magento/Framework/App/Config/Storage/WriterInterface.php @@ -7,6 +7,8 @@ */ namespace Magento\Framework\App\Config\Storage; +use Magento\Framework\App\Config\ScopeConfigInterface; + interface WriterInterface { /** @@ -17,7 +19,7 @@ interface WriterInterface * @param int $scopeId * @return void */ - public function delete($path, $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $scopeId = 0); + public function delete($path, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeId = 0); /** * Save config value to storage @@ -28,5 +30,5 @@ interface WriterInterface * @param int $scopeId * @return void */ - public function save($path, $value, $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, $scopeId = 0); + public function save($path, $value, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeId = 0); } diff --git a/lib/internal/Magento/Framework/App/Config/Value.php b/lib/internal/Magento/Framework/App/Config/Value.php index 17c50d20b8b3a854cb7f61a319ba5d21b21e1dac..92ee527a9c48eb77a35f527c2c471c2507d1b546 100644 --- a/lib/internal/Magento/Framework/App/Config/Value.php +++ b/lib/internal/Magento/Framework/App/Config/Value.php @@ -91,7 +91,7 @@ class Value extends \Magento\Framework\Model\AbstractModel implements \Magento\F { return (string)$this->_config->getValue( $this->getPath(), - $this->getScope() ?: \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + $this->getScope() ?: ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $this->getScopeCode() ); } diff --git a/lib/internal/Magento/Framework/App/MutableScopeConfig.php b/lib/internal/Magento/Framework/App/MutableScopeConfig.php index c94fb73f9d5e4cb35ddf246710bf464a932a25ad..418817465bd6f11af59b2ae5f4eaf53eea7559cd 100644 --- a/lib/internal/Magento/Framework/App/MutableScopeConfig.php +++ b/lib/internal/Magento/Framework/App/MutableScopeConfig.php @@ -9,6 +9,7 @@ namespace Magento\Framework\App; use Magento\Framework\App\Config\MutableScopeConfigInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; class MutableScopeConfig extends Config implements MutableScopeConfigInterface { @@ -24,7 +25,7 @@ class MutableScopeConfig extends Config implements MutableScopeConfigInterface public function setValue( $path, $value, - $scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, + $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null ) { if (empty($scopeCode)) { diff --git a/lib/internal/Magento/Framework/App/Request/Http.php b/lib/internal/Magento/Framework/App/Request/Http.php index c09ead13054e791d5e6bff403623545b4e24f9e6..e6e502cf38171387aef13cdf606845d082f8664d 100644 --- a/lib/internal/Magento/Framework/App/Request/Http.php +++ b/lib/internal/Magento/Framework/App/Request/Http.php @@ -7,6 +7,7 @@ */ namespace Magento\Framework\App\Request; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\Route\ConfigInterface\Proxy as ConfigInterface; use Magento\Framework\HTTP\PhpEnvironment\Request; @@ -384,7 +385,7 @@ class Http extends Request implements RequestInterface $offLoaderHeader = trim( (string)$config->getValue( self::XML_PATH_OFFLOADER_HEADER, - \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + ScopeConfigInterface::SCOPE_TYPE_DEFAULT ) ); diff --git a/lib/internal/Magento/Framework/App/Resource.php b/lib/internal/Magento/Framework/App/Resource.php index b38629a460a4fa8a7ed78c1a9e77450ec23c1c8a..b498ec9d349fea88b942b42d2ff6277c23a2449a 100644 --- a/lib/internal/Magento/Framework/App/Resource.php +++ b/lib/internal/Magento/Framework/App/Resource.php @@ -126,6 +126,7 @@ class Resource * @param string|string[] $modelEntity * @param string $connectionName * @return string + * @api */ public function getTableName($modelEntity, $connectionName = self::DEFAULT_READ_RESOURCE) { diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface.php index c6798f7ce4ab659e813488a155d0aa467ac41449..d96a4af89eac0d2a4c3932995643c1cbccec25e5 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface.php @@ -1,12 +1,15 @@ <?php /** - * Routes configuration interface - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\App\Route; +/** + * Routes configuration interface + * + * @api + */ interface ConfigInterface { /** @@ -32,7 +35,7 @@ interface ConfigInterface * * @param string $frontName * @param string $scope - * @return array + * @return string[] */ public function getModulesByFrontName($frontName, $scope = null); } diff --git a/lib/internal/Magento/Framework/App/ScopeInterface.php b/lib/internal/Magento/Framework/App/ScopeInterface.php index d244ec5bf3a1f612722795b72e938fef77f1102f..77c8a8b890ac209400fdf8005636ee869d8ecfd0 100644 --- a/lib/internal/Magento/Framework/App/ScopeInterface.php +++ b/lib/internal/Magento/Framework/App/ScopeInterface.php @@ -7,11 +7,6 @@ namespace Magento\Framework\App; interface ScopeInterface { - /** - * Default scope type - */ - const SCOPE_DEFAULT = 'default'; - /** * Retrieve scope code * diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Cache/Type/ConfigTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Cache/Type/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c6887709da50fbd2bf4fdb303f3e256749a4e197 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/Cache/Type/ConfigTest.php @@ -0,0 +1,169 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Test\Unit\Cache\Type; + +use Magento\Framework\App\Cache\Type\FrontendPool; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\Cache\Type\Config + */ + protected $model; + + /** + * @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $frontendMock; + + protected function setUp() + { + $cacheFrontendPoolMock = $this->getMockBuilder('Magento\Framework\App\Cache\Type\FrontendPool') + ->disableOriginalConstructor() + ->getMock(); + $this->model = (new ObjectManager($this))->getObject( + 'Magento\Framework\App\Cache\Type\Config', + ['cacheFrontendPool' => $cacheFrontendPoolMock] + ); + $this->frontendMock = $this->getMock('Magento\Framework\Cache\FrontendInterface'); + $cacheFrontendPoolMock->expects($this->once()) + ->method('get') + ->with(\Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER) + ->willReturn($this->frontendMock); + } + + /** + * @param string $method + * @param array $params + * @param mixed $expectedResult + * @dataProvider proxyMethodDataProvider + */ + public function testProxyMethod($method, $params, $expectedResult) + { + $helper = new \Magento\Framework\TestFramework\Unit\Helper\ProxyTesting(); + $result = $helper->invokeWithExpectations($this->model, $this->frontendMock, $method, $params, $expectedResult); + $this->assertSame($expectedResult, $result); + } + + /** + * @return array + */ + public function proxyMethodDataProvider() + { + return [ + ['test', ['record_id'], 111], + ['load', ['record_id'], '111'], + ['remove', ['record_id'], true], + ['getBackend', [], $this->getMock('Zend_Cache_Backend')], + ['getLowLevelFrontend', [], $this->getMock('Zend_Cache_Core')], + ]; + } + + public function testSave() + { + $expectedResult = new \stdClass(); + $this->frontendMock->expects( + $this->once() + )->method( + 'save' + )->with( + 'test_value', + 'test_id', + ['test_tag_one', 'test_tag_two', \Magento\Framework\App\Cache\Type\Config::CACHE_TAG], + 111 + )->will( + $this->returnValue($expectedResult) + ); + $actualResult = $this->model->save('test_value', 'test_id', ['test_tag_one', 'test_tag_two'], 111); + $this->assertSame($expectedResult, $actualResult); + } + + public function testCleanModeAll() + { + $expectedResult = new \stdClass(); + $this->frontendMock->expects( + $this->once() + )->method( + 'clean' + )->with( + \Zend_Cache::CLEANING_MODE_MATCHING_TAG, + [\Magento\Framework\App\Cache\Type\Config::CACHE_TAG] + )->will( + $this->returnValue($expectedResult) + ); + $actualResult = $this->model->clean( + \Zend_Cache::CLEANING_MODE_ALL, + ['ignored_tag_one', 'ignored_tag_two'] + ); + $this->assertSame($expectedResult, $actualResult); + } + + public function testCleanModeMatchingTag() + { + $expectedResult = new \stdClass(); + $this->frontendMock->expects( + $this->once() + )->method( + 'clean' + )->with( + \Zend_Cache::CLEANING_MODE_MATCHING_TAG, + ['test_tag_one', 'test_tag_two', \Magento\Framework\App\Cache\Type\Config::CACHE_TAG] + )->will( + $this->returnValue($expectedResult) + ); + $actualResult = $this->model->clean( + \Zend_Cache::CLEANING_MODE_MATCHING_TAG, + ['test_tag_one', 'test_tag_two'] + ); + $this->assertSame($expectedResult, $actualResult); + } + + /** + * @param bool $fixtureResultOne + * @param bool $fixtureResultTwo + * @param bool $expectedResult + * @dataProvider cleanModeMatchingAnyTagDataProvider + */ + public function testCleanModeMatchingAnyTag($fixtureResultOne, $fixtureResultTwo, $expectedResult) + { + $this->frontendMock->expects( + $this->at(0) + )->method( + 'clean' + )->with( + \Zend_Cache::CLEANING_MODE_MATCHING_TAG, + ['test_tag_one', \Magento\Framework\App\Cache\Type\Config::CACHE_TAG] + )->will( + $this->returnValue($fixtureResultOne) + ); + $this->frontendMock->expects( + $this->at(1) + )->method( + 'clean' + )->with( + \Zend_Cache::CLEANING_MODE_MATCHING_TAG, + ['test_tag_two', \Magento\Framework\App\Cache\Type\Config::CACHE_TAG] + )->will( + $this->returnValue($fixtureResultTwo) + ); + $actualResult = $this->model->clean( + \Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, + ['test_tag_one', 'test_tag_two'] + ); + $this->assertEquals($expectedResult, $actualResult); + } + + public function cleanModeMatchingAnyTagDataProvider() + { + return [ + 'failure, failure' => [false, false, false], + 'failure, success' => [false, true, true], + 'success, failure' => [true, false, true], + 'success, success' => [true, true, true] + ]; + } +} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/Storage/WriterTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/Storage/WriterTest.php index 57040f09ee4dd82eb4ec80df99f0b827cc859573..887a1cf477663f00253816aed0bfdd273cd6fe5f 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Config/Storage/WriterTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/Storage/WriterTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\App\Test\Unit\Config\Storage; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ScopeInterface; class WriterTest extends \PHPUnit_Framework_TestCase @@ -40,7 +41,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase { $this->resource->expects($this->once()) ->method('deleteConfig') - ->with('path', ScopeInterface::SCOPE_DEFAULT, 0); + ->with('path', ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0); $this->model->delete('path'); } @@ -58,7 +59,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase { $this->resource->expects($this->once()) ->method('saveConfig') - ->with('path', 'value', ScopeInterface::SCOPE_DEFAULT, 0); + ->with('path', 'value', ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0); $this->model->save('path', 'value'); } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Request/HttpTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Request/HttpTest.php index 090580da2726653983a7ed76ec9f16405393092f..8bfb9be2f3bb253932ba96c59d11d9819b704b50 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Request/HttpTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Request/HttpTest.php @@ -9,6 +9,7 @@ namespace Magento\Framework\App\Test\Unit\Request; +use Magento\Framework\App\Config\ScopeConfigInterface; use \Magento\Framework\App\Request\Http; use Magento\Framework\App\ScopeInterface; use Zend\Stdlib\Parameters; @@ -325,7 +326,7 @@ class HttpTest extends \PHPUnit_Framework_TestCase ->getMock(); $configMock->expects($this->exactly($configCall)) ->method('getValue') - ->with(\Magento\Framework\App\Request\Http::XML_PATH_OFFLOADER_HEADER, ScopeInterface::SCOPE_DEFAULT) + ->with(\Magento\Framework\App\Request\Http::XML_PATH_OFFLOADER_HEADER, ScopeConfigInterface::SCOPE_TYPE_DEFAULT) ->willReturn($configOffloadHeader); $this->objectManager->expects($this->exactly($configCall)) ->method('get') diff --git a/lib/internal/Magento/Framework/App/Test/Unit/View/Deployment/VersionTest.php b/lib/internal/Magento/Framework/App/Test/Unit/View/Deployment/VersionTest.php old mode 100755 new mode 100644 index 65e059a58a3158ec6e5a627ad6ed85923a0317ac..092aeecbeff26912c6eec7d5070801c9f87312cb --- a/lib/internal/Magento/Framework/App/Test/Unit/View/Deployment/VersionTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/View/Deployment/VersionTest.php @@ -3,11 +3,13 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Framework\App\Test\Unit\View\Deployment; use \Magento\Framework\App\View\Deployment\Version; +/** + * Class VersionTest + */ class VersionTest extends \PHPUnit_Framework_TestCase { /** diff --git a/lib/internal/Magento/Framework/AppInterface.php b/lib/internal/Magento/Framework/AppInterface.php index 7bf9c70ada1b61682217450ee8aa846de7e01943..b363aff3a23479b3d3820e4055c2d4368450ffad 100644 --- a/lib/internal/Magento/Framework/AppInterface.php +++ b/lib/internal/Magento/Framework/AppInterface.php @@ -17,7 +17,7 @@ interface AppInterface /** * Magento version */ - const VERSION = '0.74.0-beta6'; + const VERSION = '0.74.0-beta7'; /** * Launch application diff --git a/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Bare.php b/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Bare.php index b856e8608aa726ebf0f32e07ecb01ad7ac8d7d6f..cae35e66ff83d2b40b562b77aaaeaed4d030221e 100644 --- a/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Bare.php +++ b/lib/internal/Magento/Framework/Cache/Frontend/Decorator/Bare.php @@ -27,6 +27,18 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface $this->_frontend = $frontend; } + /** + * Set frontend + * + * @param \Magento\Framework\Cache\FrontendInterface $frontend + * @return $this + */ + protected function setFrontend(\Magento\Framework\Cache\FrontendInterface $frontend) + { + $this->_frontend = $frontend; + return $this; + } + /** * Retrieve cache frontend instance being decorated * @@ -42,7 +54,7 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface */ public function test($identifier) { - return $this->_frontend->test($identifier); + return $this->_getFrontend()->test($identifier); } /** @@ -50,7 +62,7 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface */ public function load($identifier) { - return $this->_frontend->load($identifier); + return $this->_getFrontend()->load($identifier); } /** @@ -60,7 +72,7 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface */ public function save($data, $identifier, array $tags = [], $lifeTime = null) { - return $this->_frontend->save($data, $identifier, $tags, $lifeTime); + return $this->_getFrontend()->save($data, $identifier, $tags, $lifeTime); } /** @@ -68,7 +80,7 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface */ public function remove($identifier) { - return $this->_frontend->remove($identifier); + return $this->_getFrontend()->remove($identifier); } /** @@ -76,7 +88,7 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface */ public function clean($mode = \Zend_Cache::CLEANING_MODE_ALL, array $tags = []) { - return $this->_frontend->clean($mode, $tags); + return $this->_getFrontend()->clean($mode, $tags); } /** @@ -84,7 +96,7 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface */ public function getBackend() { - return $this->_frontend->getBackend(); + return $this->_getFrontend()->getBackend(); } /** @@ -92,6 +104,6 @@ class Bare implements \Magento\Framework\Cache\FrontendInterface */ public function getLowLevelFrontend() { - return $this->_frontend->getLowLevelFrontend(); + return $this->_getFrontend()->getLowLevelFrontend(); } } diff --git a/lib/internal/Magento/Framework/Cache/Frontend/Decorator/TagScope.php b/lib/internal/Magento/Framework/Cache/Frontend/Decorator/TagScope.php index 32c9e4422417cf220a28db98137ef954a26ba705..0f74b1894865754521bd9b595f0b14a5572e1e8c 100644 --- a/lib/internal/Magento/Framework/Cache/Frontend/Decorator/TagScope.php +++ b/lib/internal/Magento/Framework/Cache/Frontend/Decorator/TagScope.php @@ -45,7 +45,7 @@ class TagScope extends \Magento\Framework\Cache\Frontend\Decorator\Bare */ public function save($data, $identifier, array $tags = [], $lifeTime = null) { - $tags[] = $this->_tag; + $tags[] = $this->getTag(); return parent::save($data, $identifier, $tags, $lifeTime); } @@ -59,16 +59,16 @@ class TagScope extends \Magento\Framework\Cache\Frontend\Decorator\Bare if ($mode == \Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG) { $result = false; foreach ($tags as $tag) { - if (parent::clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [$tag, $this->_tag])) { + if (parent::clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [$tag, $this->getTag()])) { $result = true; } } } else { if ($mode == \Zend_Cache::CLEANING_MODE_ALL) { $mode = \Zend_Cache::CLEANING_MODE_MATCHING_TAG; - $tags = [$this->_tag]; + $tags = [$this->getTag()]; } else { - $tags[] = $this->_tag; + $tags[] = $this->getTag(); } $result = parent::clean($mode, $tags); } diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsList.php b/lib/internal/Magento/Framework/Config/ConfigOptionsList.php index ac1a90652f40c07dc382b094e655a4cd289a5700..a520389a24a748a8379f9cb7ae6163da7ffb1b62 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsList.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsList.php @@ -32,20 +32,20 @@ class ConfigOptionsList implements ConfigOptionsListInterface * Input keys for the options */ const INPUT_KEY_ENCRYPTION_KEY = 'key'; - const INPUT_KEY_SESSION_SAVE = 'session_save'; - const INPUT_KEY_DEFINITION_FORMAT = 'definition_format'; - const INPUT_KEY_DB_HOST = 'db_host'; - const INPUT_KEY_DB_NAME = 'db_name'; - const INPUT_KEY_DB_USER = 'db_user'; - const INPUT_KEY_DB_PASSWORD = 'db_password'; - const INPUT_KEY_DB_PREFIX = 'db_prefix'; - const INPUT_KEY_DB_MODEL = 'db_model'; - const INPUT_KEY_DB_INIT_STATEMENTS = 'db_init_statements'; + const INPUT_KEY_SESSION_SAVE = 'session-save'; + const INPUT_KEY_DEFINITION_FORMAT = 'definition-format'; + const INPUT_KEY_DB_HOST = 'db-host'; + const INPUT_KEY_DB_NAME = 'db-name'; + const INPUT_KEY_DB_USER = 'db-user'; + const INPUT_KEY_DB_PASSWORD = 'db-password'; + const INPUT_KEY_DB_PREFIX = 'db-prefix'; + const INPUT_KEY_DB_MODEL = 'db-model'; + const INPUT_KEY_DB_INIT_STATEMENTS = 'db-init-statements'; const INPUT_KEY_RESOURCE = 'resource'; /**#@-*/ /**#@+ - * Values for session_save + * Values for session-save */ const SESSION_SAVE_FILES = 'files'; const SESSION_SAVE_DB = 'db'; diff --git a/lib/internal/Magento/Framework/Data/Collection/Filesystem.php b/lib/internal/Magento/Framework/Data/Collection/Filesystem.php index 817c4b420519697de1ad27984ca0d286e151a125..cec62bc94a82b655866f71fe5118c13336868bef 100644 --- a/lib/internal/Magento/Framework/Data/Collection/Filesystem.php +++ b/lib/internal/Magento/Framework/Data/Collection/Filesystem.php @@ -284,6 +284,7 @@ class Filesystem extends \Magento\Framework\Data\Collection * @param bool $printQuery * @param bool $logQuery * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @throws \Exception */ public function loadData($printQuery = false, $logQuery = false) @@ -668,6 +669,7 @@ class Filesystem extends \Magento\Framework\Data\Collection * @param string $value * @param string $type * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function addFilter($field, $value, $type = 'and') { @@ -696,7 +698,7 @@ class Filesystem extends \Magento\Framework\Data\Collection */ public function filterCallbackLike($field, $filterValue, $row) { - $filterValueRegex = str_replace('%', '(.*?)', preg_quote($filterValue, '/')); + $filterValueRegex = str_replace('%', '(.*?)', str_replace('\'', '', preg_quote($filterValue, '/'))); return (bool)preg_match("/^{$filterValueRegex}\$/i", $row[$field]); } diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Collection/FilesystemTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Collection/FilesystemTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b764079a841b7f07f35dc9a692b9ffeb6968fe5f --- /dev/null +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Collection/FilesystemTest.php @@ -0,0 +1,30 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Data\Test\Unit\Collection; + +class FilesystemTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Framework\Data\Collection\Filesystem */ + private $model; + + public function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $objectManager->getObject('Magento\Framework\Data\Collection\Filesystem'); + } + + public function testFilterCallbackLike() + { + $field = 'field'; + $row = [$field => 'beginning_filter_target_end',]; + $filterValueSuccess = new \Zend_Db_Expr('%filter_target%'); + $filterValueFailure = new \Zend_Db_Expr('%not_found_in_the_row%'); + + $this->assertTrue($this->model->filterCallbackLike($field, $filterValueSuccess, $row)); + $this->assertFalse($this->model->filterCallbackLike($field, $filterValueFailure, $row)); + } +} diff --git a/lib/internal/Magento/Framework/Data/etc/argument/types.xsd b/lib/internal/Magento/Framework/Data/etc/argument/types.xsd index 5b6b6cedf73ce0d6d6d61ca840ba4ccd6018c115..065e8de3d18029677614bc5cc90855d53727c18e 100644 --- a/lib/internal/Magento/Framework/Data/etc/argument/types.xsd +++ b/lib/internal/Magento/Framework/Data/etc/argument/types.xsd @@ -46,6 +46,21 @@ </xs:complexContent> </xs:complexType> + <xs:complexType name="configurableObject" mixed="true"> + <xs:complexContent> + <xs:extension base="argumentType"> + <xs:sequence> + <xs:element name="argument" type="argumentType" minOccurs="1" maxOccurs="unbounded"> + <xs:key name="argumentConfigurableObjectName"> + <xs:selector xpath="argument"/> + <xs:field xpath="@name"/> + </xs:key> + </xs:element> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="number"> <xs:complexContent> <xs:extension base="argumentType"/> diff --git a/lib/internal/Magento/Framework/Locale/ConfigInterface.php b/lib/internal/Magento/Framework/Locale/ConfigInterface.php index 3539f09409a800e83665f16d58871797f96161d0..e0f28fd015c33675eaed0445956c7a728a5e0d84 100644 --- a/lib/internal/Magento/Framework/Locale/ConfigInterface.php +++ b/lib/internal/Magento/Framework/Locale/ConfigInterface.php @@ -5,19 +5,24 @@ */ namespace Magento\Framework\Locale; +/** + * Provides access to locale-related config information + * + * @api + */ interface ConfigInterface { /** * Get list pre-configured allowed locales * - * @return array + * @return string[] */ public function getAllowedLocales(); /** * Get list pre-configured allowed currencies * - * @return array + * @return string[] */ public function getAllowedCurrencies(); } diff --git a/lib/internal/Magento/Framework/Locale/Currency.php b/lib/internal/Magento/Framework/Locale/Currency.php index 5d3c5a9ec9b7e961d870e4a458bc4b3fa69b5b89..f0be6c12172278b8e3a32b86848f296cd606d96a 100644 --- a/lib/internal/Magento/Framework/Locale/Currency.php +++ b/lib/internal/Magento/Framework/Locale/Currency.php @@ -7,6 +7,10 @@ namespace Magento\Framework\Locale; class Currency implements \Magento\Framework\Locale\CurrencyInterface { + /** + * Default currency + */ + const DEFAULT_CURRENCY = 'USD'; /** * @var array */ @@ -45,20 +49,15 @@ class Currency implements \Magento\Framework\Locale\CurrencyInterface } /** - * Retrieve currency code - * - * @return string + * @inheritdoc */ public function getDefaultCurrency() { - return \Magento\Framework\Locale\CurrencyInterface::DEFAULT_CURRENCY; + return self::DEFAULT_CURRENCY; } /** - * Create \Zend_Currency object for current locale - * - * @param string $currency - * @return \Magento\Framework\Currency + * @inheritdoc */ public function getCurrency($currency) { diff --git a/lib/internal/Magento/Framework/Locale/CurrencyInterface.php b/lib/internal/Magento/Framework/Locale/CurrencyInterface.php index 774f7d5120f3cead8f11e9d7545928e62634faa2..00bbc4452eedd604d19cb9144d1f38e9417e9568 100644 --- a/lib/internal/Magento/Framework/Locale/CurrencyInterface.php +++ b/lib/internal/Magento/Framework/Locale/CurrencyInterface.php @@ -5,27 +5,22 @@ */ namespace Magento\Framework\Locale; +/** + * Provides access to currency config information + * + * @api + */ interface CurrencyInterface { /** - * Default currency - */ - const DEFAULT_CURRENCY = 'USD'; - - /** - * XML path to installed currencies - */ - const XML_PATH_ALLOW_CURRENCIES_INSTALLED = 'system/currency/installed'; - - /** - * Retrieve currency code + * Retrieve default currency code * * @return string */ public function getDefaultCurrency(); /** - * Create \Magento\Framework\Currency object for current locale + * Create Currency object for current locale * * @param string $currency * @return \Magento\Framework\Currency diff --git a/lib/internal/Magento/Framework/Locale/Resolver.php b/lib/internal/Magento/Framework/Locale/Resolver.php index b78be470920ec0638dd4a8a786d13b97470277f3..6a81f60cc5a0cda5d7d55a31f7f9b599e905c94a 100644 --- a/lib/internal/Magento/Framework/Locale/Resolver.php +++ b/lib/internal/Magento/Framework/Locale/Resolver.php @@ -9,6 +9,10 @@ use Magento\Framework\App\Config\ScopeConfigInterface; class Resolver implements ResolverInterface { + /** + * Default locale + */ + const DEFAULT_LOCALE = 'en_US'; /** * Default locale code * @@ -85,7 +89,7 @@ class Resolver implements ResolverInterface if (!$this->defaultLocale) { $locale = $this->scopeConfig->getValue($this->getDefaultLocalePath(), $this->scopeType); if (!$locale) { - $locale = ResolverInterface::DEFAULT_LOCALE; + $locale = self::DEFAULT_LOCALE; } $this->defaultLocale = $locale; } diff --git a/lib/internal/Magento/Framework/Locale/ResolverInterface.php b/lib/internal/Magento/Framework/Locale/ResolverInterface.php index 08add444266f073aaa354935b6857be2c7edd34f..a17932ed8628870f7ce9f086946807498c836807 100644 --- a/lib/internal/Magento/Framework/Locale/ResolverInterface.php +++ b/lib/internal/Magento/Framework/Locale/ResolverInterface.php @@ -5,13 +5,13 @@ */ namespace Magento\Framework\Locale; +/** + * Manages locale config information + * + * @api + */ interface ResolverInterface { - /** - * Default locale - */ - const DEFAULT_LOCALE = 'en_US'; - /** * Return path to default locale * diff --git a/lib/internal/Magento/Framework/Locale/Test/Unit/CurrencyTest.php b/lib/internal/Magento/Framework/Locale/Test/Unit/CurrencyTest.php index 01552d3a972294bd649141074cc91f985829743b..226e8d4d8508be64e2a9a9454aeaa94cbb3de243 100644 --- a/lib/internal/Magento/Framework/Locale/Test/Unit/CurrencyTest.php +++ b/lib/internal/Magento/Framework/Locale/Test/Unit/CurrencyTest.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Locale\Test\Unit; +use Magento\Framework\Locale\Currency; use Magento\Framework\Locale\CurrencyInterface; class CurrencyTest extends \PHPUnit_Framework_TestCase @@ -68,7 +69,7 @@ class CurrencyTest extends \PHPUnit_Framework_TestCase public function testGetDefaultCurrency() { - $expectedDefaultCurrency = CurrencyInterface::DEFAULT_CURRENCY; + $expectedDefaultCurrency = Currency::DEFAULT_CURRENCY; $retrievedDefaultCurrency = $this->testCurrencyObject->getDefaultCurrency(); $this->assertEquals($expectedDefaultCurrency, $retrievedDefaultCurrency); } diff --git a/lib/internal/Magento/Framework/Locale/Validator.php b/lib/internal/Magento/Framework/Locale/Validator.php index b30727562c45755db8b67dfb00be40c18bae09fc..0cdf265af01b329f3a87eca97ac8de8c723902b6 100644 --- a/lib/internal/Magento/Framework/Locale/Validator.php +++ b/lib/internal/Magento/Framework/Locale/Validator.php @@ -29,10 +29,12 @@ class Validator } /** - * Validate locale code + * Validate locale code. Code must be in the list of allowed locales. * * @param string $localeCode * @return bool + * + * @api */ public function isValid($localeCode) { diff --git a/lib/internal/Magento/Framework/Message/Factory.php b/lib/internal/Magento/Framework/Message/Factory.php index 4c16064b5b6599dbb98f48307601dfff7eda1ee3..be7e3c9bb566a041c026a5916f4e51364e06b07d 100644 --- a/lib/internal/Magento/Framework/Message/Factory.php +++ b/lib/internal/Magento/Framework/Message/Factory.php @@ -45,11 +45,12 @@ class Factory } /** - * Create message instance with specified parameters + * Create a message instance of a given type with given text. * - * @param string $type - * @param string $text - * @throws \InvalidArgumentException + * @param string $type The message type to create, must correspond to a message type under the + * namespace Magento\Framework\Message\ + * @param string $text The text to inject into the message + * @throws \InvalidArgumentException Exception gets thrown if type does not correspond to a valid Magento message * @return MessageInterface */ public function create($type, $text) diff --git a/lib/internal/Magento/Framework/Message/Manager.php b/lib/internal/Magento/Framework/Message/Manager.php index 73b212a58e3ee88769bd653a815c15ecafde2578..815296c80bad2d8453564f10797ade913a2e5c7f 100644 --- a/lib/internal/Magento/Framework/Message/Manager.php +++ b/lib/internal/Magento/Framework/Message/Manager.php @@ -14,6 +14,10 @@ use Psr\Log\LoggerInterface as Logger; */ class Manager implements ManagerInterface { + /** + * Default message group + */ + const DEFAULT_GROUP = 'default'; /** * @var Session */ @@ -74,9 +78,7 @@ class Manager implements ManagerInterface } /** - * Retrieve default message group - * - * @return string + * {@inheritdoc} */ public function getDefaultGroup() { @@ -95,7 +97,7 @@ class Manager implements ManagerInterface } /** - * Retrieve messages + * @inheritdoc * * @param string|null $group * @param bool $clear @@ -118,7 +120,7 @@ class Manager implements ManagerInterface } /** - * Adding new message to message collection + * @inheritdoc * * @param MessageInterface $message * @param string|null $group @@ -133,7 +135,7 @@ class Manager implements ManagerInterface } /** - * Adding messages array to message collection + * @inheritdoc * * @param MessageInterface[] $messages * @param string|null $group @@ -148,7 +150,7 @@ class Manager implements ManagerInterface } /** - * Adding new error message + * @inheritdoc * * @param string $message * @param string|null $group @@ -161,7 +163,7 @@ class Manager implements ManagerInterface } /** - * Adding new warning message + * @inheritdoc * * @param string $message * @param string|null $group @@ -174,7 +176,7 @@ class Manager implements ManagerInterface } /** - * Adding new notice message + * @inheritdoc * * @param string $message * @param string|null $group @@ -187,7 +189,7 @@ class Manager implements ManagerInterface } /** - * Adding new success message + * @inheritdoc * * @param string $message * @param string|null $group @@ -200,7 +202,7 @@ class Manager implements ManagerInterface } /** - * Adds messages array to message collection, but doesn't add duplicates to it + * @inheritdoc * * @param MessageInterface[]|MessageInterface $messages * @param string|null $group @@ -244,7 +246,7 @@ class Manager implements ManagerInterface } /** - * Not Magento exception handling + * @inheritdoc * * @param \Exception $exception * @param string $alternativeText diff --git a/lib/internal/Magento/Framework/Message/ManagerInterface.php b/lib/internal/Magento/Framework/Message/ManagerInterface.php index 36851dc866c49be7c9e0f0ea15490c79b776db4a..dd73d2a2fcfbc8acbd9aabdef42a3f5d59616f4d 100644 --- a/lib/internal/Magento/Framework/Message/ManagerInterface.php +++ b/lib/internal/Magento/Framework/Message/ManagerInterface.php @@ -6,15 +6,12 @@ namespace Magento\Framework\Message; /** - * Message manager interface + * Adds different types of messages to the session, and allows access to existing messages. + * + * @api */ interface ManagerInterface { - /** - * Default message group - */ - const DEFAULT_GROUP = 'default'; - /** * Retrieve messages * @@ -32,7 +29,7 @@ interface ManagerInterface public function getDefaultGroup(); /** - * Adding new message to message collection + * Adds new message to message collection * * @param MessageInterface $message * @param string|null $group @@ -41,7 +38,7 @@ interface ManagerInterface public function addMessage(MessageInterface $message, $group = null); /** - * Adding messages array to message collection + * Adds messages array to message collection * * @param array $messages * @param string|null $group @@ -50,7 +47,7 @@ interface ManagerInterface public function addMessages(array $messages, $group = null); /** - * Adding new error message + * Adds new error message * * @param string $message * @param string|null $group @@ -59,7 +56,7 @@ interface ManagerInterface public function addError($message, $group = null); /** - * Adding new warning message + * Adds new warning message * * @param string $message * @param string|null $group @@ -68,7 +65,7 @@ interface ManagerInterface public function addWarning($message, $group = null); /** - * Adding new notice message + * Adds new notice message * * @param string $message * @param string|null $group @@ -77,7 +74,7 @@ interface ManagerInterface public function addNotice($message, $group = null); /** - * Adding new success message + * Adds new success message * * @param string $message * @param string|null $group @@ -86,7 +83,7 @@ interface ManagerInterface public function addSuccess($message, $group = null); /** - * Adds messages array to message collection, but doesn't add duplicates to it + * Adds messages array to message collection, without adding duplicate messages * * @param array|MessageInterface $messages * @param string|null $group @@ -95,7 +92,7 @@ interface ManagerInterface public function addUniqueMessages($messages, $group = null); /** - * Not Magento exception handling + * Adds a message describing an exception. Does not contain Exception handling logic. * * @param \Exception $exception * @param string $alternativeText diff --git a/lib/internal/Magento/Framework/Message/MessageInterface.php b/lib/internal/Magento/Framework/Message/MessageInterface.php index e5342f49ac042e79fb0b572fca328a1285ab8b22..d9d60e047b1713fd6a6288a86b2a7b74b8ddae0a 100644 --- a/lib/internal/Magento/Framework/Message/MessageInterface.php +++ b/lib/internal/Magento/Framework/Message/MessageInterface.php @@ -6,7 +6,9 @@ namespace Magento\Framework\Message; /** - * Interface for message + * Represent a message with a type, content text, and an isSticky attribute to prevent message from being cleared. + * + * @api */ interface MessageInterface { diff --git a/lib/internal/Magento/Framework/Message/Session.php b/lib/internal/Magento/Framework/Message/Session.php index da86d172577a4f0ae18dce396deaf6688cd42d2e..8ceb66543e370ccf34321cef02be325bedb2cf85 100644 --- a/lib/internal/Magento/Framework/Message/Session.php +++ b/lib/internal/Magento/Framework/Message/Session.php @@ -8,6 +8,6 @@ namespace Magento\Framework\Message; /** * Message session model */ -class Session extends \Magento\Framework\Session\Generic +class Session extends \Magento\Framework\Session\SessionManager { } diff --git a/lib/internal/Magento/Framework/Message/Test/Unit/ManagerTest.php b/lib/internal/Magento/Framework/Message/Test/Unit/ManagerTest.php index c4980974bc289f00167474eb50040197e020cb66..d65a5459a4ee92dae76a266743cb03d39c3220b6 100644 --- a/lib/internal/Magento/Framework/Message/Test/Unit/ManagerTest.php +++ b/lib/internal/Magento/Framework/Message/Test/Unit/ManagerTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Message\Test\Unit; +use Magento\Framework\Message\Manager; use Magento\Framework\Message\MessageInterface; use Magento\Framework\Message\ManagerInterface; @@ -86,7 +87,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase public function testGetDefaultGroup() { - $this->assertEquals(ManagerInterface::DEFAULT_GROUP, $this->model->getDefaultGroup()); + $this->assertEquals(Manager::DEFAULT_GROUP, $this->model->getDefaultGroup()); $customDefaultGroup = 'some_group'; $customManager = $this->objectManager->getObject( @@ -117,7 +118,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase )->method( 'getData' )->with( - ManagerInterface::DEFAULT_GROUP + Manager::DEFAULT_GROUP )->will( $this->returnValue(null) ); @@ -126,7 +127,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase )->method( 'setData' )->with( - ManagerInterface::DEFAULT_GROUP, + Manager::DEFAULT_GROUP, $messageCollection )->will( $this->returnValue($this->session) @@ -136,7 +137,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase )->method( 'getData' )->with( - ManagerInterface::DEFAULT_GROUP + Manager::DEFAULT_GROUP )->will( $this->returnValue($messageCollection) ); @@ -161,7 +162,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase )->method( 'getData' )->with( - ManagerInterface::DEFAULT_GROUP + Manager::DEFAULT_GROUP )->will( $this->returnValue($messageCollection) ); @@ -209,7 +210,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase )->method( 'getData' )->with( - ManagerInterface::DEFAULT_GROUP + Manager::DEFAULT_GROUP )->will( $this->returnValue($messageCollection) ); diff --git a/lib/internal/Magento/Framework/Model/Resource/AbstractResource.php b/lib/internal/Magento/Framework/Model/Resource/AbstractResource.php index 831dcf5ae71fb2f832a7372efd8abdfe49a0ac40..c2a9bd81aad960e498303fae9f00a0f333a26272 100644 --- a/lib/internal/Magento/Framework/Model/Resource/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/Resource/AbstractResource.php @@ -61,6 +61,7 @@ abstract class AbstractResource * Start resource transaction * * @return $this + * @api */ public function beginTransaction() { @@ -73,6 +74,7 @@ abstract class AbstractResource * * @param array $callback * @return $this + * @api */ public function addCommitCallback($callback) { @@ -85,6 +87,7 @@ abstract class AbstractResource * Commit resource transaction * * @return $this + * @api */ public function commit() { @@ -109,6 +112,7 @@ abstract class AbstractResource * Roll back resource transaction * * @return $this + * @api */ public function rollBack() { diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php index 351365b08d9eb57d45b6b65a50c53edbb93d482c..ba80e64a256222d7d02ac7eaae6cd95f7ec3717a 100644 --- a/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php @@ -233,6 +233,7 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso * * @throws LocalizedException * @return string + * @api */ public function getIdFieldName() { @@ -248,6 +249,7 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso * * @throws LocalizedException * @return string + * @api */ public function getMainTable() { @@ -262,6 +264,7 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso * * @param string $tableName * @return string + * @api */ public function getTable($tableName) { @@ -391,6 +394,7 @@ abstract class AbstractDb extends \Magento\Framework\Model\Resource\AbstractReso * @param \Magento\Framework\Model\AbstractModel $object * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @api */ public function save(\Magento\Framework\Model\AbstractModel $object) { diff --git a/lib/internal/Magento/Framework/Object/Copy.php b/lib/internal/Magento/Framework/Object/Copy.php index 9145e0aba3bc9b9a106863967d2b7c5a3bd8b124..c0d87722872490ec10c4b15efb33fc3f2385fd33 100644 --- a/lib/internal/Magento/Framework/Object/Copy.php +++ b/lib/internal/Magento/Framework/Object/Copy.php @@ -47,6 +47,8 @@ class Copy * @param array|\Magento\Framework\Object $target * @param string $root * @return array|\Magento\Framework\Object|null the value of $target + * + * @api */ public function copyFieldsetToTarget($fieldset, $aspect, $source, $target, $root = 'global') { @@ -91,6 +93,8 @@ class Copy * @param array|\Magento\Framework\Object $source * @param string $root * @return array $data + * + * @api */ public function getDataFromFieldset($fieldset, $aspect, $source, $root = 'global') { diff --git a/lib/internal/Magento/Framework/Object/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Object/Copy/Config/Data/Proxy.php new file mode 100644 index 0000000000000000000000000000000000000000..ea974307333d3da54ea344c57d8b72331f30a44f --- /dev/null +++ b/lib/internal/Magento/Framework/Object/Copy/Config/Data/Proxy.php @@ -0,0 +1,124 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Object\Copy\Config\Data; + +/** + * Proxy class for @see \Magento\Framework\Object\Copy\Config\Data + */ +class Proxy extends \Magento\Framework\Object\Copy\Config\Data +{ + /** + * Object Manager instance + * + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $_objectManager = null; + + /** + * Proxied instance name + * + * @var string + */ + protected $_instanceName = null; + + /** + * Proxied instance + * + * @var \Magento\Framework\Object\Copy\Config\Data + */ + protected $_subject = null; + + /** + * Instance shareability flag + * + * @var bool + */ + protected $_isShared = null; + + /** + * Proxy constructor + * + * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param string $instanceName + * @param bool $shared + */ + public function __construct( + \Magento\Framework\ObjectManagerInterface $objectManager, + $instanceName = '\\Magento\\Framework\\Object\\Copy\\Config\\Data', + $shared = true + ) { + $this->_objectManager = $objectManager; + $this->_instanceName = $instanceName; + $this->_isShared = $shared; + } + + /** + * @return array + */ + public function __sleep() + { + return ['_subject', '_isShared']; + } + + /** + * Retrieve ObjectManager from global scope + * + * @return void + */ + public function __wakeup() + { + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + } + + /** + * Clone proxied instance + * + * @return void + */ + public function __clone() + { + $this->_subject = clone $this->_getSubject(); + } + + /** + * Get proxied instance + * + * @return \Magento\Framework\Object\Copy\Config\Data + */ + protected function _getSubject() + { + if (!$this->_subject) { + $this->_subject = true === $this->_isShared + ? $this->_objectManager->get($this->_instanceName) + : $this->_objectManager->create($this->_instanceName); + } + return $this->_subject; + } + + /** + * {@inheritdoc} + */ + public function merge(array $config) + { + return $this->_getSubject()->merge($config); + } + + /** + * {@inheritdoc} + */ + public function get($path = null, $default = null) + { + return $this->_getSubject()->get($path, $default); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + return $this->_getSubject()->reset(); + } +} diff --git a/lib/internal/Magento/Framework/ObjectManager/Profiler/FactoryDecorator.php b/lib/internal/Magento/Framework/ObjectManager/Profiler/FactoryDecorator.php index ad3864500bbc9502a1d8d6ecbaa296c76ac82d19..895377327281b908c2a8d0944a9415bbdb400275 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Profiler/FactoryDecorator.php +++ b/lib/internal/Magento/Framework/ObjectManager/Profiler/FactoryDecorator.php @@ -8,6 +8,11 @@ namespace Magento\Framework\ObjectManager\Profiler; class FactoryDecorator implements \Magento\Framework\ObjectManager\FactoryInterface { + /** + * Name of the class that generates logging wrappers + */ + const GENERATOR_NAME = 'Magento\Framework\ObjectManager\Profiler\Code\Generator\Logger'; + /** * @var \Magento\Framework\ObjectManager\FactoryInterface */ @@ -45,9 +50,12 @@ class FactoryDecorator implements \Magento\Framework\ObjectManager\FactoryInterf { $this->log->startCreating($requestedType); $result = $this->subject->create($requestedType, $arguments); - $loggerClassName = get_class($result) . "\\Logger"; - $wrappedResult = new $loggerClassName($result, $this->log); - $this->log->stopCreating($result); - return $wrappedResult; + if ($requestedType !== self::GENERATOR_NAME) { + $loggerClassName = get_class($result) . "\\Logger"; + $wrappedResult = new $loggerClassName($result, $this->log); + $this->log->stopCreating($result); + $result = $wrappedResult; + } + return $result; } } diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Profiler/FactoryDecoratorTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Profiler/FactoryDecoratorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1d0fa91e42286c72588946788f40491de72e925e --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Profiler/FactoryDecoratorTest.php @@ -0,0 +1,75 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\ObjectManager\Test\Unit\Profiler; + +class FactoryDecoratorTest extends \PHPUnit_Framework_TestCase +{ + /** + * Name of the base class to wrap in logger + */ + const CLASS_NAME = 'Magento\Test\Di\WrappedClass'; + + /** + * Name of the wrapper class that does logging + */ + const LOGGER_NAME = 'Magento\Test\Di\WrappedClass\Logger'; + + /** + * Name of the class that generates wrappers - should not be wrapped by logger + */ + const GENERATOR_NAME = 'Magento\Framework\ObjectManager\Profiler\Code\Generator\Logger'; + + /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\ObjectManager\FactoryInterface*/ + private $objectManagerMock; + + /** @var \Magento\Framework\ObjectManager\Profiler\FactoryDecorator */ + private $model; + + public function setUp() + { + require_once __DIR__ . '/../_files/logger_classes.php'; + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManager\FactoryInterface') + ->disableOriginalConstructor() + ->getMock(); + + // Instantiate SUT + $this->model = $objectManager->getObject( + 'Magento\Framework\ObjectManager\Profiler\FactoryDecorator', + ['subject' => $this->objectManagerMock] + ); + } + + public function testCreate() + { + $baseObjectName = self::CLASS_NAME; + $baseObject = new $baseObjectName(); + + $arguments = [1, 2, 3]; + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with(self::CLASS_NAME, $arguments) + ->willReturn($baseObject); + + $this->assertInstanceOf(self::LOGGER_NAME, $this->model->create(self::CLASS_NAME, $arguments)); + } + + public function testCreateNeglectGenerator() + { + $arguments = [1, 2, 3]; + $loggerMock = $this->getMockBuilder(self::GENERATOR_NAME)->disableOriginalConstructor()->getMock(); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with(self::GENERATOR_NAME, $arguments) + ->willReturn($loggerMock); + + $this->assertSame($loggerMock, $this->model->create(self::GENERATOR_NAME, $arguments)); + } +} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/logger_classes.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/logger_classes.php new file mode 100644 index 0000000000000000000000000000000000000000..da593225f2079af53a730190a56afc0cb7715400 --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/logger_classes.php @@ -0,0 +1,26 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +//@codingStandardsIgnoreStart +namespace Magento\Test\Di { + + /** + * Test classes used for \Magento\Framework\ObjectManager\Test\Unit\Profiler\FactoryDecoratorTest + */ + class WrappedClass + { + + } +} + +namespace Magento\Test\Di\WrappedClass { + + class Logger + { + + } +} +//@codingStandardsIgnoreEnd diff --git a/lib/internal/Magento/Framework/Phrase.php b/lib/internal/Magento/Framework/Phrase.php index 992834a4816e1c14f8a56c488a739ed97c3d70f4..f4194f69b02d8c46e2907d43dc8574a2f503044f 100644 --- a/lib/internal/Magento/Framework/Phrase.php +++ b/lib/internal/Magento/Framework/Phrase.php @@ -9,7 +9,7 @@ namespace Magento\Framework; use Zend\Stdlib\JsonSerializable; use Magento\Framework\Phrase\RendererInterface; -use Magento\Framework\Phrase\Renderer\Placeholder; +use Magento\Framework\Phrase\Renderer\Placeholder as RendererPlaceholder; class Phrase implements JsonSerializable { @@ -52,11 +52,10 @@ class Phrase implements JsonSerializable */ public static function getRenderer() { - if (self::$renderer) { - return self::$renderer; - } else { - self::$renderer = new \Magento\Framework\Phrase\Renderer\Placeholder(); + if (!self::$renderer) { + self::$renderer = new RendererPlaceholder(); } + return self::$renderer; } /** @@ -98,7 +97,11 @@ class Phrase implements JsonSerializable */ public function render() { - return self::getRenderer() ? self::getRenderer()->render([$this->text], $this->arguments) : $this->text; + try { + return self::getRenderer()->render([$this->text], $this->getArguments()); + } catch (\Exception $e) { + return $this->getText(); + } } /** diff --git a/lib/internal/Magento/Framework/Phrase/Renderer/Composite.php b/lib/internal/Magento/Framework/Phrase/Renderer/Composite.php index 4b93aee4b42b041e4b09e75a7e1355258168a371..91d8f40139887d3323815a11570418482beb3750 100644 --- a/lib/internal/Magento/Framework/Phrase/Renderer/Composite.php +++ b/lib/internal/Magento/Framework/Phrase/Renderer/Composite.php @@ -17,7 +17,7 @@ class Composite implements RendererInterface protected $_renderers; /** - * @param RendererInterface[] $renderers + * @param \Magento\Framework\Phrase\RendererInterface[] $renderers * @throws \InvalidArgumentException */ public function __construct(array $renderers) diff --git a/lib/internal/Magento/Framework/Phrase/Renderer/Inline.php b/lib/internal/Magento/Framework/Phrase/Renderer/Inline.php index 5d3f094d859909e5e105b3466afb1bf9335be1d0..0cb074943f9b7a352e7062fded30cd1d406e4280 100644 --- a/lib/internal/Magento/Framework/Phrase/Renderer/Inline.php +++ b/lib/internal/Magento/Framework/Phrase/Renderer/Inline.php @@ -7,7 +7,12 @@ */ namespace Magento\Framework\Phrase\Renderer; -class Inline implements \Magento\Framework\Phrase\RendererInterface +use Magento\Framework\Phrase\RendererInterface; +use Magento\Framework\TranslateInterface; +use Magento\Framework\Translate\Inline\ProviderInterface; +use Psr\Log\LoggerInterface; + +class Inline implements RendererInterface { /** * @var \Magento\Framework\TranslateInterface @@ -19,16 +24,24 @@ class Inline implements \Magento\Framework\Phrase\RendererInterface */ protected $inlineProvider; + /** + * @var \Psr\Log\LoggerInterface + */ + protected $logger; + /** * @param \Magento\Framework\TranslateInterface $translator * @param \Magento\Framework\Translate\Inline\ProviderInterface $inlineProvider + * @param \Psr\Log\LoggerInterface $logger */ public function __construct( - \Magento\Framework\TranslateInterface $translator, - \Magento\Framework\Translate\Inline\ProviderInterface $inlineProvider + TranslateInterface $translator, + ProviderInterface $inlineProvider, + LoggerInterface $logger ) { $this->translator = $translator; $this->inlineProvider = $inlineProvider; + $this->logger = $logger; } /** @@ -37,22 +50,29 @@ class Inline implements \Magento\Framework\Phrase\RendererInterface * @param [] $source * @param [] $arguments * @return string + * @throws \Exception + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function render(array $source, array $arguments) { $text = end($source); - if (!$this->inlineProvider->get()->isAllowed()) { - return $text; - } + try { + if (!$this->inlineProvider->get()->isAllowed()) { + return $text; + } - if (strpos($text, '{{{') === false - || strpos($text, '}}}') === false - || strpos($text, '}}{{') === false - ) { - $text = '{{{' - . implode('}}{{', array_reverse($source)) - . '}}{{' . $this->translator->getTheme() . '}}}'; + if (strpos($text, '{{{') === false + || strpos($text, '}}}') === false + || strpos($text, '}}{{') === false + ) { + $text = '{{{' + . implode('}}{{', array_reverse($source)) + . '}}{{' . $this->translator->getTheme() . '}}}'; + } + } catch (\Exception $e) { + $this->logger->critical($e->getMessage()); + throw $e; } return $text; diff --git a/lib/internal/Magento/Framework/Phrase/Renderer/Placeholder.php b/lib/internal/Magento/Framework/Phrase/Renderer/Placeholder.php index a9e6ed62f35216dfef1549983e020221f5dc593b..db2551a0157465783a74bb8b17e0291a4c290a09 100644 --- a/lib/internal/Magento/Framework/Phrase/Renderer/Placeholder.php +++ b/lib/internal/Magento/Framework/Phrase/Renderer/Placeholder.php @@ -7,7 +7,9 @@ */ namespace Magento\Framework\Phrase\Renderer; -class Placeholder implements \Magento\Framework\Phrase\RendererInterface +use Magento\Framework\Phrase\RendererInterface; + +class Placeholder implements RendererInterface { /** * Render source text @@ -23,7 +25,7 @@ class Placeholder implements \Magento\Framework\Phrase\RendererInterface if ($arguments) { $placeholders = []; foreach (array_keys($arguments) as $key) { - $placeholders[] = "%" . (is_int($key) ? strval($key + 1) : $key); + $placeholders[] = '%' . (is_int($key) ? strval($key + 1) : $key); } $text = str_replace($placeholders, $arguments, $text); } diff --git a/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php b/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php index 6f981a679377e57c5924b16230d24d0ac1393f47..449b34d61c094435b6b1eb448b5d1ff7c6f3260f 100644 --- a/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php +++ b/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php @@ -7,21 +7,34 @@ */ namespace Magento\Framework\Phrase\Renderer; -class Translate implements \Magento\Framework\Phrase\RendererInterface +use Magento\Framework\Phrase\RendererInterface; +use Magento\Framework\TranslateInterface; +use Psr\Log\LoggerInterface; + +class Translate implements RendererInterface { /** * @var \Magento\Framework\TranslateInterface */ protected $translator; + /** + * @var \Psr\Log\LoggerInterface + */ + protected $logger; + /** * Renderer construct * * @param \Magento\Framework\TranslateInterface $translator + * @param \Psr\Log\LoggerInterface $logger */ - public function __construct(\Magento\Framework\TranslateInterface $translator) - { + public function __construct( + TranslateInterface $translator, + LoggerInterface $logger + ) { $this->translator = $translator; + $this->logger = $logger; } /** @@ -30,12 +43,19 @@ class Translate implements \Magento\Framework\Phrase\RendererInterface * @param [] $source * @param [] $arguments * @return string + * @throws \Exception + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function render(array $source, array $arguments) { $text = end($source); - $data = $this->translator->getData(); + try { + $data = $this->translator->getData(); + } catch (\Exception $e) { + $this->logger->critical($e->getMessage()); + throw $e; + } return array_key_exists($text, $data) ? $data[$text] : $text; } diff --git a/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/CompositeTest.php b/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/CompositeTest.php index ebb58aeade6b561ed1216a06b92a3e7e3a9c635f..b3fccdee663776d2bebeb6622907a57c263bcb5f 100644 --- a/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/CompositeTest.php +++ b/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/CompositeTest.php @@ -77,4 +77,17 @@ class CompositeTest extends \PHPUnit_Framework_TestCase $this->assertEquals($resultAfterSecond, $this->object->render([$text], $arguments)); } + + public function testRenderException() + { + $message = 'something went wrong'; + $exception = new \Exception($message); + + $this->rendererOne->expects($this->once()) + ->method('render') + ->willThrowException($exception); + + $this->setExpectedException('Exception', $message); + $this->object->render(['text'], []); + } } diff --git a/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/InlineTest.php b/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/InlineTest.php index 59174a88a4e90dd8e97cce09d590eeab03eb6fce..68be45b7e99b7cb17065a5ed5208c3ece0a0cc38 100644 --- a/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/InlineTest.php +++ b/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/InlineTest.php @@ -8,28 +8,36 @@ namespace Magento\Framework\Phrase\Test\Unit\Renderer; class InlineTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\TranslateInterface + * @var \Magento\Framework\TranslateInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $translator; /** * @var \Magento\Framework\Phrase\Renderer\Translate */ - protected $_renderer; + protected $renderer; /** - * @var \Magento\Framework\Translate\Inline\ProviderInterface + * @var \Magento\Framework\Translate\Inline\ProviderInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $provider; + /** + * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $loggerMock; + protected function setUp() { $this->translator = $this->getMock('Magento\Framework\TranslateInterface', [], [], '', false); $this->provider = $this->getMock('Magento\Framework\Translate\Inline\ProviderInterface', [], [], '', false); + $this->loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface') + ->getMock(); $this->renderer = new \Magento\Framework\Phrase\Renderer\Inline( $this->translator, - $this->provider + $this->provider, + $this->loggerMock ); } @@ -70,4 +78,17 @@ class InlineTest extends \PHPUnit_Framework_TestCase $this->assertEquals($text, $this->renderer->render([$text], [])); } + + public function testRenderException() + { + $message = 'something went wrong'; + $exception = new \Exception($message); + + $this->provider->expects($this->once()) + ->method('get') + ->willThrowException($exception); + + $this->setExpectedException('Exception', $message); + $this->renderer->render(['text'], []); + } } diff --git a/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/TranslateTest.php b/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/TranslateTest.php index 61d541127514c236838f4cb0e7ad01f0c8491c1a..e6581ae4825ed7d39bc43d47f4761fa2fbb3e60d 100644 --- a/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/TranslateTest.php +++ b/lib/internal/Magento/Framework/Phrase/Test/Unit/Renderer/TranslateTest.php @@ -17,14 +17,24 @@ class TranslateTest extends \PHPUnit_Framework_TestCase */ protected $_renderer; + /** + * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $loggerMock; + protected function setUp() { $this->_translator = $this->getMock('Magento\Framework\TranslateInterface', [], [], '', false); + $this->loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface') + ->getMock(); $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_renderer = $objectManagerHelper->getObject( 'Magento\Framework\Phrase\Renderer\Translate', - ['translator' => $this->_translator] + [ + 'translator' => $this->_translator, + 'logger' => $this->loggerMock + ] ); } @@ -41,4 +51,17 @@ class TranslateTest extends \PHPUnit_Framework_TestCase $this->assertEquals($translate, $this->_renderer->render([$translatedText], [])); $this->assertEquals($text, $this->_renderer->render([$text], [])); } + + public function testRenderException() + { + $message = 'something went wrong'; + $exception = new \Exception($message); + + $this->_translator->expects($this->once()) + ->method('getData') + ->willThrowException($exception); + + $this->setExpectedException('Exception', $message); + $this->_renderer->render(['text'], []); + } } diff --git a/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php b/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php index 9a0c8b2925b027ea2f72dfe536820fe2d3888181..980a8ff079c9b6f7c369099d801144ada04fdcee 100644 --- a/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php +++ b/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php @@ -89,4 +89,11 @@ interface PriceCurrencyInterface * @return \Magento\Framework\Model\AbstractModel */ public function getCurrency($scope = null, $currency = null); + + /** + * @param null|string|bool|int|\Magento\Framework\App\ScopeInterface $scope + * @param \Magento\Framework\Model\AbstractModel|string|null $currency + * @return string + */ + public function getCurrencySymbol($scope = null, $currency = null); } diff --git a/lib/internal/Magento/Framework/Pricing/Render/Amount.php b/lib/internal/Magento/Framework/Pricing/Render/Amount.php index f58510aaf55fcbe87f23b80bcd733fcd614117de..a17c6d08af4c5bf66afd4e9832f5b237c9858ba7 100644 --- a/lib/internal/Magento/Framework/Pricing/Render/Amount.php +++ b/lib/internal/Magento/Framework/Pricing/Render/Amount.php @@ -142,6 +142,14 @@ class Amount extends Template implements AmountRenderInterface return $this->priceCurrency->getCurrency()->getCurrencyCode(); } + /** + * @return string + */ + public function getDisplayCurrencySymbol() + { + return $this->priceCurrency->getCurrencySymbol(); + } + /** * @return bool */ diff --git a/lib/internal/Magento/Framework/Pricing/Render/AmountRenderInterface.php b/lib/internal/Magento/Framework/Pricing/Render/AmountRenderInterface.php index 66d0dc84a169876c2a7b025697b75fd93194eb4d..3779c69dd31ca6781a6a75b44f78c907518640df 100644 --- a/lib/internal/Magento/Framework/Pricing/Render/AmountRenderInterface.php +++ b/lib/internal/Magento/Framework/Pricing/Render/AmountRenderInterface.php @@ -50,6 +50,11 @@ interface AmountRenderInterface */ public function getDisplayCurrencyCode(); + /** + * @return string + */ + public function getDisplayCurrencySymbol(); + /** * @return string */ diff --git a/lib/internal/Magento/Framework/Pricing/Test/Unit/Render/AmountTest.php b/lib/internal/Magento/Framework/Pricing/Test/Unit/Render/AmountTest.php index 552cee4846656bd5fcdc6ce7d996bcadc0cb9535..fbf8d4f834f2fb7b1cc54af8ac75c6aad527c174 100644 --- a/lib/internal/Magento/Framework/Pricing/Test/Unit/Render/AmountTest.php +++ b/lib/internal/Magento/Framework/Pricing/Test/Unit/Render/AmountTest.php @@ -127,6 +127,15 @@ class AmountTest extends \PHPUnit_Framework_TestCase $this->assertEquals($result, $this->model->formatCurrency($amount, $includeContainer, $precision)); } + public function testGetDisplayCurrencySymbol() + { + $currencySymbol = '$'; + $this->priceCurrency->expects($this->once()) + ->method('getCurrencySymbol') + ->willReturn($currencySymbol); + $this->assertEquals($currencySymbol, $this->model->getDisplayCurrencySymbol()); + } + /** * Test case for getAdjustmentRenders method through toHtml() */ diff --git a/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php b/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php index 8552cba5a5d2458014a60e259857fc5c01becf90..6824dca09e58c813d114dba3f3c720dad27a710d 100644 --- a/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php +++ b/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php @@ -44,7 +44,7 @@ class AttributeTypeResolver implements AttributeTypeResolverInterface $config = isset($data[$context]) ? $data[$context] : []; $output = get_class($value); if (isset($config[$attributeCode])) { - $type = $config[$attributeCode]; + $type = $config[$attributeCode]['type']; $output = $this->typeProcessor->getArrayItemType($type); if (!(class_exists($output) || interface_exists($output))) { throw new \LogicException( diff --git a/lib/internal/Magento/Framework/Reflection/CustomAttributesProcessor.php b/lib/internal/Magento/Framework/Reflection/CustomAttributesProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..0a98c9e39e8c2f135b962bfbf0ef51d44924c183 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/CustomAttributesProcessor.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Reflection; + +use Magento\Framework\Phrase; +use Magento\Framework\Api\AttributeInterface; +use Magento\Framework\Api\AttributeValue; +use Magento\Framework\Api\SimpleDataObjectConverter; +use Zend\Code\Reflection\MethodReflection; +use Magento\Framework\Api\CustomAttributesDataInterface; +use Magento\Framework\Api\AttributeTypeResolverInterface; + +/** + * Processes custom attributes and produces an array for the data. + */ +class CustomAttributesProcessor +{ + /** + * @var DataObjectProcessor + */ + private $dataObjectProcessor; + + /** + * @var AttributeTypeResolverInterface + */ + private $attributeTypeResolver; + + /** + * @param DataObjectProcessor $dataObjectProcessor + * @param AttributeTypeResolverInterface $typeResolver + */ + public function __construct( + DataObjectProcessor $dataObjectProcessor, + AttributeTypeResolverInterface $typeResolver + ) { + $this->dataObjectProcessor = $dataObjectProcessor; + $this->attributeTypeResolver = $typeResolver; + } + + /** + * Writes out the custom attributes for a given object into an array. + * + * @param CustomAttributesDataInterface $objectWithCustomAttributes + * @param string $dataObjectType + * @return array + */ + public function buildOutputDataArray(CustomAttributesDataInterface $objectWithCustomAttributes, $dataObjectType) + { + $customAttributes = $objectWithCustomAttributes->getCustomAttributes(); + $result = []; + foreach ($customAttributes as $customAttribute) { + $result[] = $this->convertCustomAttribute($customAttribute, $dataObjectType); + } + return $result; + } + + /** + * Convert custom_attribute object to use flat array structure + * + * @param AttributeInterface $customAttribute + * @param string $dataObjectType + * @return array + */ + private function convertCustomAttribute(AttributeInterface $customAttribute, $dataObjectType) + { + $data = []; + $data[AttributeValue::ATTRIBUTE_CODE] = $customAttribute->getAttributeCode(); + $value = $customAttribute->getValue(); + if (is_object($value)) { + $type = $this->attributeTypeResolver->resolveObjectType( + $customAttribute->getAttributeCode(), + $value, + $dataObjectType + ); + $value = $this->dataObjectProcessor->buildOutputDataArray($value, $type); + } elseif (is_array($value)) { + $valueResult = []; + foreach ($value as $singleValue) { + if (is_object($singleValue)) { + $type = $this->attributeTypeResolver->resolveObjectType( + $customAttribute->getAttributeCode(), + $singleValue, + $dataObjectType + ); + $singleValue = $this->dataObjectProcessor->buildOutputDataArray($singleValue, $type); + } + // Cannot cast to a type because the type is unknown + $valueResult[] = $singleValue; + } + $value = $valueResult; + } + $data[AttributeValue::VALUE] = $value; + return $data; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php b/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php index 2b9977d7355f565e808b15cc539c7c892f38afa6..4adceb83c7720be26a310fe8d7dea3f19726219c 100644 --- a/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php @@ -14,54 +14,54 @@ use Zend\Code\Reflection\ClassReflection; use Zend\Code\Reflection\MethodReflection; /** - * Data object processor for de-serialization using class reflection + * Data object processor for array serialization using class reflection */ class DataObjectProcessor { - const IS_METHOD_PREFIX = 'is'; - const HAS_METHOD_PREFIX = 'has'; - const GETTER_PREFIX = 'get'; - const SERVICE_INTERFACE_METHODS_CACHE_PREFIX = 'serviceInterfaceMethodsMap'; - const BASE_MODEL_CLASS = 'Magento\Framework\Model\AbstractExtensibleModel'; - /** - * @var \Magento\Framework\Cache\FrontendInterface + * @var MethodsMap */ - protected $cache; + private $methodsMapProcessor; /** - * @var TypeProcessor + * @var TypeCaster */ - protected $typeProcessor; + private $typeCaster; /** - * @var array + * @var FieldNamer */ - protected $dataInterfaceMethodsMap = []; + private $fieldNamer; /** - * @var array + * @var ExtensionAttributesProcessor */ - protected $serviceInterfaceMethodsMap = []; + private $extensionAttributesProcessor; /** - * @var \Magento\Framework\Api\AttributeTypeResolverInterface + * @var CustomAttributesProcessor */ - protected $attributeTypeResolver; + private $customAttributesProcessor; /** - * @param \Magento\Framework\Cache\FrontendInterface $cache - * @param TypeProcessor $typeProcessor - * @param \Magento\Framework\Api\AttributeTypeResolverInterface $typeResolver + * @param MethodsMap $methodsMapProcessor + * @param TypeCaster $typeCaster + * @param FieldNamer $fieldNamer + * @param CustomAttributesProcessor $customAttributesProcessor + * @param ExtensionAttributesProcessor $extensionAttributesProcessor */ public function __construct( - \Magento\Framework\Cache\FrontendInterface $cache, - TypeProcessor $typeProcessor, - \Magento\Framework\Api\AttributeTypeResolverInterface $typeResolver + MethodsMap $methodsMapProcessor, + TypeCaster $typeCaster, + FieldNamer $fieldNamer, + CustomAttributesProcessor $customAttributesProcessor, + ExtensionAttributesProcessor $extensionAttributesProcessor ) { - $this->cache = $cache; - $this->typeProcessor = $typeProcessor; - $this->attributeTypeResolver = $typeResolver; + $this->methodsMapProcessor = $methodsMapProcessor; + $this->typeCaster = $typeCaster; + $this->fieldNamer = $fieldNamer; + $this->extensionAttributesProcessor = $extensionAttributesProcessor; + $this->customAttributesProcessor = $customAttributesProcessor; } /** @@ -74,43 +74,36 @@ class DataObjectProcessor */ public function buildOutputDataArray($dataObject, $dataObjectType) { - $methods = $this->getMethodsMap($dataObjectType); + $methods = $this->methodsMapProcessor->getMethodsMap($dataObjectType); $outputData = []; /** @var MethodReflection $method */ - foreach ($methods as $methodName => $methodReflectionData) { - // any method with parameter(s) gets ignored because we do not know the type and value of - // the parameter(s), so we are not able to process - if ($methodReflectionData['parameterCount'] > 0) { + foreach (array_keys($methods) as $methodName) { + if (!$this->methodsMapProcessor->isMethodValidForDataField($dataObjectType, $methodName)) { continue; } - $returnType = $methodReflectionData['type']; - if (substr($methodName, 0, 2) === self::IS_METHOD_PREFIX) { - $value = $dataObject->{$methodName}(); - if ($value === null && !$methodReflectionData['isRequired']) { - continue; - } - $key = SimpleDataObjectConverter::camelCaseToSnakeCase(substr($methodName, 2)); - $outputData[$key] = $this->castValueToType($value, $returnType); - } elseif (substr($methodName, 0, 3) === self::HAS_METHOD_PREFIX) { - $value = $dataObject->{$methodName}(); - if ($value === null && !$methodReflectionData['isRequired']) { - continue; - } - $key = SimpleDataObjectConverter::camelCaseToSnakeCase(substr($methodName, 3)); - $outputData[$key] = $this->castValueToType($value, $returnType); - } elseif (substr($methodName, 0, 3) === self::GETTER_PREFIX) { - $value = $dataObject->{$methodName}(); - if ($methodName === 'getCustomAttributes' && $value === []) { - continue; - } - if ($value === null && !$methodReflectionData['isRequired']) { - continue; - } - $key = SimpleDataObjectConverter::camelCaseToSnakeCase(substr($methodName, 3)); - if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES) { - $value = $this->convertCustomAttributes($value, $dataObjectType); - } elseif (is_object($value) && !($value instanceof Phrase)) { + + $value = $dataObject->{$methodName}(); + $isMethodReturnValueRequired = $this->methodsMapProcessor->isMethodReturnValueRequired( + $dataObjectType, + $methodName + ); + if ($value === null && !$isMethodReturnValueRequired) { + continue; + } + + $returnType = $this->methodsMapProcessor->getMethodReturnType($dataObjectType, $methodName); + $key = $this->fieldNamer->getFieldNameForMethodName($methodName); + if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES && $value === []) { + continue; + } + + if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES) { + $value = $this->customAttributesProcessor->buildOutputDataArray($dataObject, $dataObjectType); + } elseif ($key === "extension_attributes") { + $value = $this->extensionAttributesProcessor->buildOutputDataArray($value, $returnType); + } else { + if (is_object($value) && !($value instanceof Phrase)) { $value = $this->buildOutputDataArray($value, $returnType); } elseif (is_array($value)) { $valueResult = []; @@ -119,192 +112,16 @@ class DataObjectProcessor if (is_object($singleValue) && !($singleValue instanceof Phrase)) { $singleValue = $this->buildOutputDataArray($singleValue, $arrayElementType); } - $valueResult[] = $this->castValueToType($singleValue, $arrayElementType); + $valueResult[] = $this->typeCaster->castValueToType($singleValue, $arrayElementType); } $value = $valueResult; + } else { + $value = $this->typeCaster->castValueToType($value, $returnType); } - $outputData[$key] = $this->castValueToType($value, $returnType); } - } - return $outputData; - } - /** - * Cast the output type to the documented type. This helps for output purposes. - * - * @param mixed $value - * @param string $type - * @return mixed - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - protected function castValueToType($value, $type) - { - if ($value === null) { - return null; + $outputData[$key] = $value; } - - if ($type === "int" || $type === "integer") { - return (int)$value; - } - - if ($type === "string") { - return (string)$value; - } - - if ($type === "bool" || $type === "boolean" || $type === "true" || $type == "false") { - return (bool)$value; - } - - if ($type === "float") { - return (float)$value; - } - - if ($type === "double") { - return (double)$value; - } - - return $value; - } - - /** - * Get return type by interface name and method - * - * @param string $interfaceName - * @param string $methodName - * @return string - */ - public function getMethodReturnType($interfaceName, $methodName) - { - return $this->getMethodsMap($interfaceName)[$methodName]['type']; - } - - /** - * Convert array of custom_attributes to use flat array structure - * - * @param \Magento\Framework\Api\AttributeInterface[] $customAttributes - * @param string $dataObjectType - * @return array - */ - protected function convertCustomAttributes($customAttributes, $dataObjectType) - { - $result = []; - foreach ((array)$customAttributes as $customAttribute) { - $result[] = $this->convertCustomAttribute($customAttribute, $dataObjectType); - } - return $result; - } - - /** - * Convert custom_attribute object to use flat array structure - * - * @param \Magento\Framework\Api\AttributeInterface $customAttribute - * @param string $dataObjectType - * @return array - */ - protected function convertCustomAttribute($customAttribute, $dataObjectType) - { - $data = []; - $data[AttributeValue::ATTRIBUTE_CODE] = $customAttribute->getAttributeCode(); - $value = $customAttribute->getValue(); - if (is_object($value)) { - $type = $this->attributeTypeResolver->resolveObjectType( - $customAttribute->getAttributeCode(), - $value, - $dataObjectType - ); - $value = $this->buildOutputDataArray($value, $type); - } elseif (is_array($value)) { - $valueResult = []; - foreach ($value as $singleValue) { - if (is_object($singleValue)) { - $type = $this->attributeTypeResolver->resolveObjectType( - $customAttribute->getAttributeCode(), - $singleValue, - $dataObjectType - ); - $singleValue = $this->buildOutputDataArray($singleValue, $type); - } - // Cannot cast to a type because the type is unknown - $valueResult[] = $singleValue; - } - $value = $valueResult; - } - $data[AttributeValue::VALUE] = $value; - return $data; - } - - /** - * Return service interface or Data interface methods loaded from cache - * - * @param string $interfaceName - * @return array - * <pre> - * Service methods' reflection data stored in cache as 'methodName' => 'returnType' - * ex. - * [ - * 'create' => '\Magento\Customer\Api\Data\Customer', - * 'validatePassword' => 'boolean' - * ] - * </pre> - */ - public function getMethodsMap($interfaceName) - { - $key = self::SERVICE_INTERFACE_METHODS_CACHE_PREFIX . "-" . md5($interfaceName); - if (!isset($this->serviceInterfaceMethodsMap[$key])) { - $methodMap = $this->cache->load($key); - if ($methodMap) { - $this->serviceInterfaceMethodsMap[$key] = unserialize($methodMap); - } else { - $methodMap = $this->getMethodMapViaReflection($interfaceName); - $this->serviceInterfaceMethodsMap[$key] = $methodMap; - $this->cache->save(serialize($this->serviceInterfaceMethodsMap[$key]), $key); - } - } - return $this->serviceInterfaceMethodsMap[$key]; - } - - /** - * Use reflection to load the method information - * - * @param string $interfaceName - * @return array - */ - protected function getMethodMapViaReflection($interfaceName) - { - $methodMap = []; - $class = new ClassReflection($interfaceName); - $baseClassMethods = false; - foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { - // Include all the methods of classes inheriting from AbstractExtensibleObject. - // Ignore all the methods of AbstractExtensibleModel's parent classes - if ($method->class === self::BASE_MODEL_CLASS) { - $baseClassMethods = true; - } elseif ($baseClassMethods) { - // ReflectionClass::getMethods() sorts the methods by class (lowest in inheritance tree first) - // then by the order they are defined in the class definition - break; - } - - if ($this->isSuitableMethod($method)) { - $methodMap[$method->getName()] = $this->typeProcessor->getGetterReturnType($method); - } - } - return $methodMap; - } - - /** - * Determines if the method is suitable to be used by the processor. - * - * @param \ReflectionMethod $method - * @return bool - */ - protected function isSuitableMethod($method) - { - $isSuitableMethodType = !($method->isConstructor() || $method->isFinal() - || $method->isStatic() || $method->isDestructor()); - - $isExcludedMagicMethod = strpos($method->getName(), '__') === 0; - return $isSuitableMethodType && !$isExcludedMagicMethod; + return $outputData; } } diff --git a/lib/internal/Magento/Framework/Reflection/ExtensionAttributesProcessor.php b/lib/internal/Magento/Framework/Reflection/ExtensionAttributesProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..c2d2d69c758f8b4676da91027080fb5736d5c880 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/ExtensionAttributesProcessor.php @@ -0,0 +1,189 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Reflection; + +use Magento\Framework\Api\Config\Reader as ExtensionAttributesConfigReader; +use Magento\Framework\Api\Config\Converter; +use Magento\Framework\AuthorizationInterface; +use Magento\Framework\Phrase; +use Magento\Framework\Api\SimpleDataObjectConverter; +use Magento\Framework\Api\ExtensionAttributesInterface; +use Magento\Framework\Reflection\MethodsMap; +use Zend\Code\Reflection\MethodReflection; + +/** + * Processes extension attributes and produces an array for the data. + */ +class ExtensionAttributesProcessor +{ + /** + * @var DataObjectProcessor + */ + private $dataObjectProcessor; + + /** + * @var MethodsMap + */ + private $methodsMapProcessor; + + /** + * @var AuthorizationInterface + */ + private $authorization; + + /** + * @var ExtensionAttributesConfigReader + */ + private $configReader; + + /** + * @var bool + */ + private $isPermissionChecked; + + /** + * @var FieldNamer + */ + private $fieldNamer; + + /** + * @var TypeCaster + */ + private $typeCaster; + + /** + * @param DataObjectProcessor $dataObjectProcessor + * @param MethodsMap $methodsMapProcessor + * @param TypeCaster $typeCaster + * @param FieldNamer $fieldNamer + * @param AuthorizationInterface $authorization + * @param ExtensionAttributesConfigReader $configReader + * @param bool $isPermissionChecked + */ + public function __construct( + DataObjectProcessor $dataObjectProcessor, + MethodsMap $methodsMapProcessor, + TypeCaster $typeCaster, + FieldNamer $fieldNamer, + AuthorizationInterface $authorization, + ExtensionAttributesConfigReader $configReader, + $isPermissionChecked = false + ) { + $this->dataObjectProcessor = $dataObjectProcessor; + $this->methodsMapProcessor = $methodsMapProcessor; + $this->typeCaster = $typeCaster; + $this->fieldNamer = $fieldNamer; + $this->authorization = $authorization; + $this->configReader = $configReader; + $this->isPermissionChecked = $isPermissionChecked; + } + + /** + * Writes out the extension attributes in an array. + * + * @param ExtensionAttributeInterface $dataObject + * @param string $dataObjectType + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function buildOutputDataArray(ExtensionAttributesInterface $dataObject, $dataObjectType) + { + $methods = $this->methodsMapProcessor->getMethodsMap($dataObjectType); + $outputData = []; + + /** @var MethodReflection $method */ + foreach (array_keys($methods) as $methodName) { + if (!$this->methodsMapProcessor->isMethodValidForDataField($dataObjectType, $methodName)) { + continue; + } + + $key = $this->fieldNamer->getFieldNameForMethodName($methodName); + if ($this->isPermissionChecked && !$this->isAttributePermissionValid($dataObjectType, $key)) { + continue; + } + + $value = $dataObject->{$methodName}(); + if ($value === null) { + // all extension attributes are optional so don't need to check if isRequired + continue; + } + + $returnType = $this->methodsMapProcessor->getMethodReturnType($dataObjectType, $methodName); + + if (is_object($value) && !($value instanceof Phrase)) { + $value = $this->dataObjectProcessor->buildOutputDataArray($value, $returnType); + } elseif (is_array($value)) { + $valueResult = []; + $arrayElementType = substr($returnType, 0, -2); + foreach ($value as $singleValue) { + if (is_object($singleValue) && !($singleValue instanceof Phrase)) { + $singleValue = $this->dataObjectProcessor->buildOutputDataArray( + $singleValue, + $arrayElementType + ); + } + $valueResult[] = $this->typeCaster->castValueToType($singleValue, $arrayElementType); + } + $value = $valueResult; + } else { + $value = $this->typeCaster->castValueToType($value, $returnType); + } + + $outputData[$key] = $value; + } + + return $outputData; + } + + /** + * @param string $dataObjectType + * @param string $attributeCode + * @return bool + */ + private function isAttributePermissionValid($dataObjectType, $attributeCode) + { + $typeName = $this->getRegularTypeForExtensionAttributesType($dataObjectType); + $permissions = $this->getPermissionsForTypeAndMethod($typeName, $attributeCode); + foreach ($permissions as $permission) { + if (!$this->authorization->isAllowed($permission)) { + return false; + } + } + + return true; + } + + /** + * @param string $name + * @return string + */ + private function getRegularTypeForExtensionAttributesType($name) + { + return ltrim(str_replace('ExtensionInterface', 'Interface', $name), '\\'); + } + + /** + * @param string $typeName + * @param string $attributeCode + * @return string[] A list of permissions + */ + private function getPermissionsForTypeAndMethod($typeName, $attributeCode) + { + // TODO: Move function to the Config and hope this is cached + $attributes = $this->configReader->read(); + if (isset($attributes[$typeName]) && isset($attributes[$typeName][$attributeCode])) { + $attributeMetadata = $attributes[$typeName][$attributeCode]; + $permissions = []; + foreach ($attributeMetadata[Converter::RESOURCE_PERMISSIONS] as $permission) { + $permissions[] = $permission; + } + return $permissions; + } + + return []; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/FieldNamer.php b/lib/internal/Magento/Framework/Reflection/FieldNamer.php new file mode 100644 index 0000000000000000000000000000000000000000..2e105b9a4f666e2073124e8817a9208762740389 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/FieldNamer.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Reflection; + +use Magento\Framework\Phrase; +use Magento\Framework\Api\AttributeValue; +use Magento\Framework\Api\CustomAttributesDataInterface; +use Magento\Framework\Api\SimpleDataObjectConverter; +use Zend\Code\Reflection\ClassReflection; +use Zend\Code\Reflection\MethodReflection; + +/** + * Determines the name to use for fields in a data output array given method metadata. + */ +class FieldNamer +{ + const IS_METHOD_PREFIX = 'is'; + const HAS_METHOD_PREFIX = 'has'; + const GETTER_PREFIX = 'get'; + + /** + * Converts a method's name into a data field name. + * + * @param string $methodName + * @return string|null + */ + public function getFieldNameForMethodName($methodName) + { + if (substr($methodName, 0, 2) === self::IS_METHOD_PREFIX) { + return SimpleDataObjectConverter::camelCaseToSnakeCase(substr($methodName, 2)); + } elseif (substr($methodName, 0, 3) === self::HAS_METHOD_PREFIX) { + return SimpleDataObjectConverter::camelCaseToSnakeCase(substr($methodName, 3)); + } elseif (substr($methodName, 0, 3) === self::GETTER_PREFIX) { + return SimpleDataObjectConverter::camelCaseToSnakeCase(substr($methodName, 3)); + } + + return null; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/MethodsMap.php b/lib/internal/Magento/Framework/Reflection/MethodsMap.php new file mode 100644 index 0000000000000000000000000000000000000000..36b446d1b870a32d6f468bf77b293a63b024fabe --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/MethodsMap.php @@ -0,0 +1,180 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Reflection; + +use Zend\Code\Reflection\ClassReflection; +use Zend\Code\Reflection\MethodReflection; + +/** + * Gathers method metadata information. + */ +class MethodsMap +{ + const SERVICE_INTERFACE_METHODS_CACHE_PREFIX = 'serviceInterfaceMethodsMap'; + const BASE_MODEL_CLASS = 'Magento\Framework\Model\AbstractExtensibleModel'; + + /** + * @var \Magento\Framework\Cache\FrontendInterface + */ + private $cache; + + /** + * @var TypeProcessor + */ + private $typeProcessor; + + /** + * @var array + */ + private $serviceInterfaceMethodsMap = []; + + /** + * @var FieldNamer + */ + private $fieldNamer; + + /** + * @param \Magento\Framework\Cache\FrontendInterface $cache + * @param TypeProcessor $typeProcessor + * @param \Magento\Framework\Api\AttributeTypeResolverInterface $typeResolver + * @param FieldNamer $fieldNamer + */ + public function __construct( + \Magento\Framework\Cache\FrontendInterface $cache, + TypeProcessor $typeProcessor, + \Magento\Framework\Api\AttributeTypeResolverInterface $typeResolver, + FieldNamer $fieldNamer + ) { + $this->cache = $cache; + $this->typeProcessor = $typeProcessor; + $this->attributeTypeResolver = $typeResolver; + $this->fieldNamer = $fieldNamer; + } + + /** + * Get return type by type name and method name. + * + * @param string $typeName + * @param string $methodName + * @return string + */ + public function getMethodReturnType($typeName, $methodName) + { + return $this->getMethodsMap($typeName)[$methodName]['type']; + } + + /** + * Return service interface or Data interface methods loaded from cache + * + * @param string $interfaceName + * @return array + * <pre> + * Service methods' reflection data stored in cache as 'methodName' => 'returnType' + * ex. + * [ + * 'create' => '\Magento\Customer\Api\Data\Customer', + * 'validatePassword' => 'boolean' + * ] + * </pre> + */ + public function getMethodsMap($interfaceName) + { + $key = self::SERVICE_INTERFACE_METHODS_CACHE_PREFIX . "-" . md5($interfaceName); + if (!isset($this->serviceInterfaceMethodsMap[$key])) { + $methodMap = $this->cache->load($key); + if ($methodMap) { + $this->serviceInterfaceMethodsMap[$key] = unserialize($methodMap); + } else { + $methodMap = $this->getMethodMapViaReflection($interfaceName); + $this->serviceInterfaceMethodsMap[$key] = $methodMap; + $this->cache->save(serialize($this->serviceInterfaceMethodsMap[$key]), $key); + } + } + return $this->serviceInterfaceMethodsMap[$key]; + } + + /** + * Use reflection to load the method information + * + * @param string $interfaceName + * @return array + */ + private function getMethodMapViaReflection($interfaceName) + { + $methodMap = []; + $class = new ClassReflection($interfaceName); + $baseClassMethods = false; + foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { + // Include all the methods of classes inheriting from AbstractExtensibleObject. + // Ignore all the methods of AbstractExtensibleModel's parent classes + if ($method->class === self::BASE_MODEL_CLASS) { + $baseClassMethods = true; + } elseif ($baseClassMethods) { + // ReflectionClass::getMethods() sorts the methods by class (lowest in inheritance tree first) + // then by the order they are defined in the class definition + break; + } + + if ($this->isSuitableMethod($method)) { + $methodMap[$method->getName()] = $this->typeProcessor->getGetterReturnType($method); + } + } + return $methodMap; + } + + /** + * Determines if the method is suitable to be used by the processor. + * + * @param \ReflectionMethod $method + * @return bool + */ + private function isSuitableMethod($method) + { + $isSuitableMethodType = !($method->isConstructor() || $method->isFinal() + || $method->isStatic() || $method->isDestructor()); + + $isExcludedMagicMethod = strpos($method->getName(), '__') === 0; + return $isSuitableMethodType && !$isExcludedMagicMethod; + } + + /** + * Determines if the given method's on the given type is suitable for an output data array. + * + * @param string $type + * @param string $methodName + * @return bool + */ + public function isMethodValidForDataField($type, $methodName) + { + $methods = $this->getMethodsMap($type); + if (isset($methods[$methodName])) { + $methodMetadata = $methods[$methodName]; + // any method with parameter(s) gets ignored because we do not know the type and value of + // the parameter(s), so we are not able to process + if ($methodMetadata['parameterCount'] > 0) { + return false; + } + + return $this->fieldNamer->getFieldNameForMethodName($methodName) !== null; + } + + return false; + } + + /** + * If the method has only non-null return types + * + * @param string $type + * @param string $methodName + * @return bool + */ + public function isMethodReturnValueRequired($type, $methodName) + { + $methods = $this->getMethodsMap($type); + return $methods[$methodName]['isRequired']; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php index 8391d4643482d17da3c717dbbc732b7c43002b19..68902f3851380d368c88ca8e2357bada00a2de7d 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php @@ -62,7 +62,13 @@ class AttributeTypeResolverTest extends \PHPUnit_Framework_TestCase $code = 'some_code'; $value = new \stdClass(); $context = '\Some\Class'; - $config = ['Some\Class' => ['some_code' => '\Magento\Framework\Object']]; + $config = [ + 'Some\Class' => [ + 'some_code' => [ + 'type' => '\Magento\Framework\Object', + ], + ] + ]; $this->typeProcessor->expects($this->once()) ->method('getArrayItemType') @@ -82,7 +88,13 @@ class AttributeTypeResolverTest extends \PHPUnit_Framework_TestCase $code = 'some_code'; $value = new \stdClass(); $context = '\Some\Class'; - $config = ['Some\Class' => ['some_code' => '\Some\Class']]; + $config = [ + 'Some\Class' => [ + 'some_code' => [ + 'type' => '\Some\Class', + ] + ] + ]; $this->typeProcessor->expects($this->once()) ->method('getArrayItemType') diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesObject.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesObject.php new file mode 100644 index 0000000000000000000000000000000000000000..66077712a43b337238402748fe9ccf9c4b0db5f2 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesObject.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Reflection\Test\Unit; + +use Magento\Framework\Api\ExtensionAttributesInterface; + +/** + * Dummy data object to be used by ExtensionAttributesProcessorTest + */ +class ExtensionAttributesObject implements ExtensionAttributesInterface +{ + /** + * @return string + */ + public function getAttrName() + { + return 'attrName'; + } + + /** + * @return bool + */ + public function isActive() + { + return false; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesProcessorTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8da0c1f734f710da1c69d28c9e9f4ac02999db86 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesProcessorTest.php @@ -0,0 +1,172 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Reflection\Test\Unit; + +use Magento\Framework\Api\Config\Converter; +use Magento\Framework\Api\Config\Reader; +use Magento\Framework\AuthorizationInterface; +use Magento\Framework\Reflection\DataObjectProcessor; +use Magento\Framework\Reflection\ExtensionAttributesProcessor; +use Magento\Framework\Reflection\FieldNamer; +use Magento\Framework\Reflection\MethodsMap; +use Magento\Framework\Reflection\TypeCaster; + +/** + * ExtensionAttributesProcessor test + */ +class ExtensionAttributesProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ExtensionAttributesProcessor + */ + private $model; + + /** + * @var DataObjectProcessor + */ + private $dataObjectProcessorMock; + + /** + * @var MethodsMap + */ + private $methodsMapProcessorMock; + + /** + * @var FieldNamer + */ + private $fieldNamerMock; + + /** + * @var TypeCaster + */ + private $typeCasterMock; + + /** + * @var Reader + */ + private $configReaderMock; + + /** + * @var AuthorizationInterface + */ + private $authorizationMock; + /** + * Set up helper. + */ + public function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->dataObjectProcessorMock = $this->getMockBuilder('Magento\Framework\Reflection\DataObjectProcessor') + ->disableOriginalConstructor() + ->getMock(); + $this->methodsMapProcessorMock = $this->getMockBuilder('Magento\Framework\Reflection\MethodsMap') + ->disableOriginalConstructor() + ->getMock(); + $this->typeCasterMock = $this->getMockBuilder('Magento\Framework\Reflection\TypeCaster') + ->disableOriginalConstructor() + ->getMock(); + $this->fieldNamerMock = $this->getMockBuilder('Magento\Framework\Reflection\FieldNamer') + ->disableOriginalConstructor() + ->getMock(); + $this->configReaderMock = $this->getMockBuilder('Magento\Framework\Api\Config\Reader') + ->disableOriginalConstructor() + ->getMock(); + $this->authorizationMock = $this->getMockBuilder('Magento\Framework\AuthorizationInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->model = $objectManager->getObject( + 'Magento\Framework\Reflection\ExtensionAttributesProcessor', + [ + 'dataObjectProcessor' => $this->dataObjectProcessorMock, + 'methodsMapProcessor' => $this->methodsMapProcessorMock, + 'typeCaster' => $this->typeCasterMock, + 'fieldNamer' => $this->fieldNamerMock, + 'authorization' => $this->authorizationMock, + 'configReader' => $this->configReaderMock, + 'isPermissionChecked' => true, + ] + ); + } + + /** + * @param bool $isPermissionAllowed + * @param array $expectedValue + * @dataProvider buildOutputDataArrayWithPermissionProvider + */ + public function testBuildOutputDataArrayWithPermission($isPermissionAllowed, $expectedValue) + { + $dataObject = new \Magento\Framework\Reflection\Test\Unit\ExtensionAttributesObject(); + $dataObjectType = 'Magento\Framework\Reflection\Test\Unit\ExtensionAttributesObject'; + $methodName = 'getAttrName'; + $attributeName = 'attr_name'; + $attributeValue = 'attrName'; + + $this->methodsMapProcessorMock->expects($this->once()) + ->method('getMethodsMap') + ->with($dataObjectType) + ->will($this->returnValue([$methodName => []])); + $this->methodsMapProcessorMock->expects($this->once()) + ->method('isMethodValidForDataField') + ->with($dataObjectType, $methodName) + ->will($this->returnValue(true)); + $this->fieldNamerMock->expects($this->once()) + ->method('getFieldNameForMethodName') + ->with($methodName) + ->will($this->returnValue($attributeName)); + $permissionName = 'Magento_Permission'; + $this->configReaderMock->expects($this->once()) + ->method('read') + ->will($this->returnValue([ + $dataObjectType => [ + $attributeName => [ Converter::RESOURCE_PERMISSIONS => [ $permissionName ] ] + ] + ])); + $this->authorizationMock->expects($this->once()) + ->method('isAllowed') + ->with($permissionName) + ->will($this->returnValue($isPermissionAllowed)); + + if ($isPermissionAllowed) { + $this->methodsMapProcessorMock->expects($this->once()) + ->method('getMethodReturnType') + ->with($dataObjectType, $methodName) + ->will($this->returnValue('string')); + $this->typeCasterMock->expects($this->once()) + ->method('castValueToType') + ->with($attributeValue, 'string') + ->will($this->returnValue($attributeValue)); + } + + $value = $this->model->buildOutputDataArray( + $dataObject, + $dataObjectType + ); + + $this->assertEquals( + $value, + $expectedValue + ); + } + + public function buildOutputDataArrayWithPermissionProvider() + { + return [ + 'permission allowed' => [ + true, + [ + 'attr_name' => 'attrName', + ], + ], + 'permission not allowed' => [ + false, + [], + ], + ]; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/FieldNamerTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/FieldNamerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1d498a940ec1a437ccc546e3629df37767748eeb --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/FieldNamerTest.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Reflection\Test\Unit; + +use Magento\Framework\Reflection\FieldNamer; + +/** + * Field namer Test + */ +class FieldNamerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var FieldNamer + */ + private $model; + + /** + * Set up helper. + */ + public function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $objectManager->getObject('Magento\Framework\Reflection\FieldNamer'); + } + + /** + * @param string $methodName + * @param string $expectedName + * @dataProvider methodNameProvider + */ + public function testGetFieldNameForMethodName($methodName, $expectedName) + { + $value = $this->model->getFieldNameForMethodName($methodName); + $this->assertEquals($value, $expectedName); + } + + /** + * @return array + */ + public function methodNameProvider() + { + return [ + 'isMethod' => ['isValid', 'valid'], + 'getMethod' => ['getValue', 'value'], + 'hasMethod' => ['hasStuff', 'stuff'], + 'randomMethod' => ['randomMethod', null], + ]; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/MethodsMapTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/MethodsMapTest.php new file mode 100644 index 0000000000000000000000000000000000000000..82f859897da9bfdcdd8f26de0ef7d3201712f699 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/MethodsMapTest.php @@ -0,0 +1,174 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Reflection\Test\Unit; + +use Magento\Framework\Reflection\MethodsMap; +use Magento\Framework\Reflection\TypeProcessor; +use Magento\Framework\Reflection\FieldNamer; + +/** + * MethodsMap test + */ +class MethodsMapTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MethodsMap + */ + private $model; + + /** + * Set up helper. + */ + public function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $cacheMock = $this->getMockBuilder('Magento\Framework\Cache\FrontendInterface') + ->getMockForAbstractClass(); + $cacheMock->expects($this->any()) + ->method('save'); + $cacheMock->expects($this->any()) + ->method('load') + ->will($this->returnValue(null)); + + $attributeTypeResolverMock = $this->getMockBuilder('Magento\Framework\Api\AttributeTypeResolverInterface') + ->getMockForAbstractClass(); + $fieldNamerMock = $this->getMockBuilder('Magento\Framework\Reflection\FieldNamer') + ->getMockForAbstractClass(); + $this->model = $objectManager->getObject( + 'Magento\Framework\Reflection\MethodsMap', + [ + 'cache' => $cacheMock, + 'typeProcessor' => new TypeProcessor(), + 'typeResolver' => $attributeTypeResolverMock, + 'fieldNamer' => $fieldNamerMock, + ] + ); + } + + public function testGetMethodReturnType() + { + $this->assertEquals( + 'string', + $this->model->getMethodReturnType('Magento\Framework\Reflection\FieldNamer', 'getFieldNameForMethodName') + ); + $this->assertEquals( + 'mixed', + $this->model->getMethodReturnType('Magento\Framework\Reflection\TypeCaster', 'castValueToType') + ); + $this->assertEquals( + 'array', + $this->model->getMethodReturnType('Magento\Framework\Reflection\MethodsMap', 'getMethodsMap') + ); + } + + public function testGetMethodsMap() + { + $methodsMap = $this->model->getMethodsMap('Magento\Framework\Reflection\MethodsMap'); + $this->assertEquals( + $methodsMap, + [ + 'getMethodReturnType' => [ + 'type' => 'string', + 'isRequired' => true, + 'description' => null, + 'parameterCount' => 2, + ], + 'getMethodsMap' => [ + 'type' => 'array', + 'isRequired' => true, + 'description' => "<pre> Service methods' reflection data stored in cache as 'methodName' => " + . "'returnType' ex. [ 'create' => '\Magento\Customer\Api\Data\Customer', 'validatePassword' " + . "=> 'boolean' ] </pre>", + 'parameterCount' => 1, + ], + 'isMethodValidForDataField' => [ + 'type' => 'bool', + 'isRequired' => true, + 'description' => null, + 'parameterCount' => 2, + ], + 'isMethodReturnValueRequired' => [ + 'type' => 'bool', + 'isRequired' => true, + 'description' => null, + 'parameterCount' => 2, + ], + ] + ); + } + + /** + * @param string $type + * @param string $methodName + * @param bool $expectedResult + * @dataProvider isMethodValidForDataFieldProvider + */ + public function testIsMethodValidForDataField($type, $methodName, $expectedResult) + { + $this->assertEquals($this->model->isMethodValidForDataField($type, $methodName), $expectedResult); + } + + /** + * @return array + */ + public function isMethodValidForDataFieldProvider() + { + return [ + 'MethodsMap#isMethodValidForDataField' => [ + 'Magento\Framework\Reflection\MethodsMap', + 'isMethodValidForDataField', + false, + ], + 'DataObject#getAttrName' => [ + 'Magento\Framework\Reflection\Test\Unit\DataObject', + 'getAttrName', + true, + ], + 'DataObject#isActive' => [ + 'Magento\Framework\Reflection\Test\Unit\DataObject', + 'isActive', + true, + ], + ]; + } + + /** + * @param string $type + * @param string $methodName + * @param bool $expectedResult + * @dataProvider isMethodReturnValueRequiredProvider + */ + public function testIsMethodReturnValueRequired($type, $methodName, $expectedResult) + { + $this->assertEquals($this->model->isMethodValidForDataField($type, $methodName), $expectedResult); + } + + /** + * @return array + */ + public function isMethodReturnValueRequiredProvider() + { + return [ + 'DataObject#getAttrName' => [ + 'Magento\Framework\Reflection\Test\Unit\DataObject', + 'getAttrName', + true, + ], + 'DataObject#isActive' => [ + 'Magento\Framework\Reflection\Test\Unit\DataObject', + 'isActive', + true, + ], + 'FieldNamer#getFieldNameForMethodName' => [ + 'Magento\Framework\Reflection\FieldNamer', + 'getFieldNameForMethodName', + false, + ], + ]; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeCasterTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeCasterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8f7afdbbedcb05e103f92c6c982d5a0686cf7481 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeCasterTest.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Reflection\Test\Unit; + +use Magento\Framework\Reflection\TypeCaster; + +/** + * Type caster Test + */ +class TypeCasterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var TypeCaster + */ + private $model; + + /** + * Set up helper. + */ + public function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $objectManager->getObject('Magento\Framework\Reflection\TypeCaster'); + } + + /** + * @param mixed $origValue + * @param string $typeToCast + * @param mixed $expectedValue + * @dataProvider typeCastValueProvider + */ + public function testCastValues($origValue, $typeToCast, $expectedValue) + { + $value = $this->model->castValueToType($origValue, $typeToCast); + $this->assertTrue($value === $expectedValue); + } + + /** + * @return array + */ + public function typeCastValueProvider() + { + return [ + 'null' => [null, 'int', null], + 'int' => ['1', 'int', 1], + 'integer' => ['1', 'integer', 1], + 'string' => ['1', 'string', '1'], + 'bool 0' => ['0', 'bool', false], + 'bool 1' => ['1', 'bool', true], + 'boolean 0' => ['0', 'boolean', false], + 'boolean 1' => ['1', 'boolean', true], + 'true' => ['1', 'true', true], + 'false' => ['0', 'false', false], + 'float' => ['1.03', 'float', 1.03], + 'double' => ['1.30', 'double', 1.30], + ]; + } +} diff --git a/lib/internal/Magento/Framework/Reflection/TypeCaster.php b/lib/internal/Magento/Framework/Reflection/TypeCaster.php new file mode 100644 index 0000000000000000000000000000000000000000..185b86c1d880b14061f3271da5de4885bf56cf29 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/TypeCaster.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Reflection; + +/** + * Casts values to the type given. + */ +class TypeCaster +{ + /** + * Cast the output type to the documented type. This helps for consistent output (e.g. JSON). + * + * @param mixed $value + * @param string $type + * @return mixed + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function castValueToType($value, $type) + { + if ($value === null) { + return null; + } + + if ($type === "int" || $type === "integer") { + return (int)$value; + } + + if ($type === "string") { + return (string)$value; + } + + if ($type === "bool" || $type === "boolean" || $type === "true" || $type == "false") { + return (bool)$value; + } + + if ($type === "float") { + return (float)$value; + } + + if ($type === "double") { + return (double)$value; + } + + return $value; + } +} diff --git a/lib/internal/Magento/Framework/Search/Dynamic/DataProviderFactory.php b/lib/internal/Magento/Framework/Search/Dynamic/DataProviderFactory.php index 1cfc1477a7957b46fe1f58f752749b3d8a4193a2..1b534b4dbf4991c3c5f71f2b8009bd6efd9f20df 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/DataProviderFactory.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/DataProviderFactory.php @@ -33,7 +33,7 @@ class DataProviderFactory ScopeConfigInterface $scopeConfig, $configPath, $dataProviders, - $scope = ScopeInterface::SCOPE_DEFAULT + $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT ) { $this->objectManager = $objectManager; $configValue = $scopeConfig->getValue($configPath, $scope); diff --git a/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php b/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php index bba9824e19083f82aa5c249338bf16d2d4da5575..80ac66bb04e62950ae6a7d4dedc4e0fd8dd148d4 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php @@ -33,7 +33,7 @@ class IntervalFactory ScopeConfigInterface $scopeConfig, $configPath, $intervals, - $scope = ScopeInterface::SCOPE_DEFAULT + $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT ) { $this->objectManager = $objectManager; $configValue = $scopeConfig->getValue($configPath, $scope); diff --git a/lib/internal/Magento/Framework/Search/Request/Mapper.php b/lib/internal/Magento/Framework/Search/Request/Mapper.php index e2dcbef74cda6ab201ed6bdd7dc6b3dcda916cd7..d69d5e4e6d6689170096767166c1cc44fba09d6d 100644 --- a/lib/internal/Magento/Framework/Search/Request/Mapper.php +++ b/lib/internal/Magento/Framework/Search/Request/Mapper.php @@ -14,6 +14,11 @@ use Magento\Framework\Phrase; */ class Mapper { + /** + * @var QueryInterface + */ + private $rootQuery; + /** * @var array */ @@ -45,9 +50,9 @@ class Mapper private $objectManager; /** - * @var QueryInterface + * @var string */ - private $rootQuery = null; + private $rootQueryName; /** * @param \Magento\Framework\ObjectManagerInterface $objectManager @@ -70,26 +75,26 @@ class Mapper $this->queries = $queries; $this->aggregations = $aggregations; $this->filters = $filters; - - $this->rootQuery = $this->get($rootQueryName); + $this->rootQueryName = $rootQueryName; } /** * Get Query Interface by name * - * @param string $queryName * @return QueryInterface * @throws \Exception * @throws \InvalidArgumentException * @throws StateException */ - private function get($queryName) + public function getRootQuery() { - $this->mappedQueries = []; - $this->mappedFilters = []; - $query = $this->mapQuery($queryName); - $this->validate(); - return $query; + if (!$this->rootQuery) { + $this->mappedQueries = []; + $this->mappedFilters = []; + $this->rootQuery = $this->mapQuery($this->rootQueryName); + $this->validate(); + } + return $this->rootQuery; } /** @@ -304,14 +309,6 @@ class Mapper $this->validateNotUsed($this->filters, $this->mappedFilters, 'Filter %1 is not used in request hierarchy'); } - /** - * @return QueryInterface - */ - public function getRootQuery() - { - return $this->rootQuery; - } - /** * Build BucketInterface[] from array * diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/DimensionsTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/DimensionsTest.php index 3b37a0bf3d574e10044e2bdea2f8c4b2c2eccebb..5b0736c5fa2ef890b1362bae14c6d9b70f38bf97 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/DimensionsTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/DimensionsTest.php @@ -6,6 +6,7 @@ namespace Magento\Framework\Search\Test\Unit\Adapter\Mysql; +use Magento\Framework\App\Config\ScopeConfigInterface; use \Magento\Framework\Search\Adapter\Mysql\Dimensions; use Magento\Framework\Search\Adapter\Mysql\Dimensions as DimensionsBuilder; @@ -103,7 +104,7 @@ class DimensionsTest extends \PHPUnit_Framework_TestCase { $tableAlias = 'search_index'; $name = 'scope'; - $value = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT; + $value = ScopeConfigInterface::SCOPE_TYPE_DEFAULT; $scopeId = -123456; $this->dimension->expects($this->once()) diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Dynamic/IntervalFactoryTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Dynamic/IntervalFactoryTest.php index 0d7b52e00630adde68df4600dd353d1d7e314207..232f789de3ae77014a26ee1e251dbcce6235d0e5 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Dynamic/IntervalFactoryTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Dynamic/IntervalFactoryTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Test\Unit\Dynamic; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Search\Dynamic\IntervalInterface; use Magento\Framework\App\ScopeInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -63,7 +64,7 @@ class IntervalFactoryTest extends \PHPUnit_Framework_TestCase { $this->scopeConfig->expects($this->once()) ->method('getValue') - ->with(self::CONFIG_PATH, ScopeInterface::SCOPE_DEFAULT) + ->with(self::CONFIG_PATH, ScopeConfigInterface::SCOPE_TYPE_DEFAULT) ->willReturn(self::CONFIG_PATH . 't'); $this->objectManager->expects($this->once()) ->method('create') @@ -83,7 +84,7 @@ class IntervalFactoryTest extends \PHPUnit_Framework_TestCase { $this->scopeConfig->expects($this->once()) ->method('getValue') - ->with(self::CONFIG_PATH, ScopeInterface::SCOPE_DEFAULT) + ->with(self::CONFIG_PATH, ScopeConfigInterface::SCOPE_TYPE_DEFAULT) ->willReturn('t'); $this->factoryCreate(); @@ -97,7 +98,7 @@ class IntervalFactoryTest extends \PHPUnit_Framework_TestCase { $this->scopeConfig->expects($this->once()) ->method('getValue') - ->with(self::CONFIG_PATH, ScopeInterface::SCOPE_DEFAULT) + ->with(self::CONFIG_PATH, ScopeConfigInterface::SCOPE_TYPE_DEFAULT) ->willReturn(self::CONFIG_PATH . 't'); $this->objectManager->expects($this->once()) ->method('create') diff --git a/lib/internal/Magento/Framework/Session/Generic.php b/lib/internal/Magento/Framework/Session/Generic.php index dd7da87c933a3fff8be209f77e93b77c5eebea1a..bfaf48d74ee9d7f4851e181e8e69f06437da8993 100644 --- a/lib/internal/Magento/Framework/Session/Generic.php +++ b/lib/internal/Magento/Framework/Session/Generic.php @@ -7,38 +7,4 @@ namespace Magento\Framework\Session; class Generic extends SessionManager { - /** - * Constructor - * - * @param \Magento\Framework\App\Request\Http $request - * @param SidResolverInterface $sidResolver - * @param \Magento\Framework\Session\Config\ConfigInterface $sessionConfig - * @param SaveHandlerInterface $saveHandler - * @param ValidatorInterface $validator - * @param StorageInterface $storage - * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager - * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory - */ - public function __construct( - \Magento\Framework\App\Request\Http $request, - SidResolverInterface $sidResolver, - \Magento\Framework\Session\Config\ConfigInterface $sessionConfig, - SaveHandlerInterface $saveHandler, - ValidatorInterface $validator, - StorageInterface $storage, - \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, - \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory - ) { - parent::__construct( - $request, - $sidResolver, - $sessionConfig, - $saveHandler, - $validator, - $storage, - $cookieManager, - $cookieMetadataFactory - ); - $this->start(); - } } diff --git a/lib/internal/Magento/Framework/Session/SessionManager.php b/lib/internal/Magento/Framework/Session/SessionManager.php index 17636fa0776804b433129011dd25b2edaec33275..c66672e87ca8f6b7098a3ecf17a0df582dad6072 100644 --- a/lib/internal/Magento/Framework/Session/SessionManager.php +++ b/lib/internal/Magento/Framework/Session/SessionManager.php @@ -11,6 +11,7 @@ use Magento\Framework\Session\Config\ConfigInterface; /** * Session Manager + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SessionManager implements SessionManagerInterface { @@ -87,8 +88,11 @@ class SessionManager implements SessionManagerInterface protected $cookieMetadataFactory; /** - * Constructor - * + * @var \Magento\Framework\App\State + */ + private $appState; + + /** * @param \Magento\Framework\App\Request\Http $request * @param SidResolverInterface $sidResolver * @param ConfigInterface $sessionConfig @@ -97,6 +101,8 @@ class SessionManager implements SessionManagerInterface * @param StorageInterface $storage * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory + * @param \Magento\Framework\App\State $appState + * @throws \Magento\Framework\Exception\SessionException */ public function __construct( \Magento\Framework\App\Request\Http $request, @@ -106,7 +112,8 @@ class SessionManager implements SessionManagerInterface ValidatorInterface $validator, StorageInterface $storage, \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, - \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory + \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory, + \Magento\Framework\App\State $appState ) { $this->request = $request; $this->sidResolver = $sidResolver; @@ -116,9 +123,11 @@ class SessionManager implements SessionManagerInterface $this->storage = $storage; $this->cookieManager = $cookieManager; $this->cookieMetadataFactory = $cookieMetadataFactory; + $this->appState = $appState; // Enable session.use_only_cookies ini_set('session.use_only_cookies', '1'); + $this->start(); } /** @@ -152,12 +161,25 @@ class SessionManager implements SessionManagerInterface /** * Configure session handler and start session * + * @throws \Magento\Framework\Exception\SessionException * @return $this */ public function start() { if (!$this->isSessionExists()) { \Magento\Framework\Profiler::start('session_start'); + + try { + $this->appState->getAreaCode(); + } catch (\Magento\Framework\Exception\LocalizedException $e) { + throw new \Magento\Framework\Exception\SessionException( + new \Magento\Framework\Phrase( + 'Area code not set: Area code must be set before starting a session.' + ), + $e + ); + } + // Need to apply the config options so they can be ready by session_start $this->initIniOptions(); $this->registerSaveHandler(); diff --git a/lib/internal/Magento/Framework/Shell.php b/lib/internal/Magento/Framework/Shell.php index 0652d49d039e0c43d21375d3d87153db78b1e243..2372ba4088571c89d7865d4a9d2b7523fdd6e1eb 100644 --- a/lib/internal/Magento/Framework/Shell.php +++ b/lib/internal/Magento/Framework/Shell.php @@ -49,7 +49,7 @@ class Shell implements ShellInterface $command = $this->commandRenderer->render($command, $arguments); $this->log($command); - $disabled = explode(',', ini_get('disable_functions')); + $disabled = explode(',', str_replace(' ', ',', ini_get('disable_functions'))); if (in_array('exec', $disabled)) { throw new Exception\LocalizedException(new \Magento\Framework\Phrase("exec function is disabled.")); } diff --git a/lib/internal/Magento/Framework/Simplexml/Config.php b/lib/internal/Magento/Framework/Simplexml/Config.php index 4e1265ebd4a4c180d7bbc4a8b84b0334b5b1676a..2f45cd6550b87a9417f2e50355866765c26d2a2b 100644 --- a/lib/internal/Magento/Framework/Simplexml/Config.php +++ b/lib/internal/Magento/Framework/Simplexml/Config.php @@ -118,12 +118,12 @@ class Config */ public function getNode($path = null) { - if (!$this->_xml instanceof Element) { + if (!$this->getXml() instanceof Element) { return false; } elseif ($path === null) { - return $this->_xml; + return $this->getXml(); } else { - return $this->_xml->descend($path); + return $this->getXml()->descend($path); } } @@ -135,11 +135,12 @@ class Config */ public function getXpath($xpath) { - if (empty($this->_xml)) { + $xml = $this->getXml(); + if (empty($xml)) { return false; } - if (!($result = @$this->_xml->xpath($xpath))) { + if (!($result = @$xml->xpath($xpath))) { return false; } @@ -476,7 +477,7 @@ class Config if (!empty($string)) { $xml = simplexml_load_string($string, $this->_elementClass); if ($xml) { - $this->_xml = $xml; + $this->setXml($xml); return true; } } @@ -493,7 +494,7 @@ class Config { $xml = simplexml_import_dom($dom, $this->_elementClass); if ($xml) { - $this->_xml = $xml; + $this->setXml($xml); return true; } @@ -510,7 +511,7 @@ class Config */ public function setNode($path, $value, $overwrite = true) { - $this->_xml->setNode($path, $value, $overwrite); + $this->getXml()->setNode($path, $value, $overwrite); return $this; } @@ -575,4 +576,14 @@ class Config { $this->_xml = null; } + + /** + * Getter for xml element + * + * @return Element + */ + protected function getXml() + { + return $this->_xml; + } } diff --git a/lib/internal/Magento/Framework/Test/Unit/PhraseTest.php b/lib/internal/Magento/Framework/Test/Unit/PhraseTest.php index f3e8c8d9e0195e9fd64d659d6a020d71c8f93f88..72bff033c0c7402e782aa7bd350afa041912e7fc 100755 --- a/lib/internal/Magento/Framework/Test/Unit/PhraseTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/PhraseTest.php @@ -5,7 +5,7 @@ */ namespace Magento\Framework\Test\Unit; -use \Magento\Framework\Phrase; +use Magento\Framework\Phrase; class PhraseTest extends \PHPUnit_Framework_TestCase { @@ -19,11 +19,6 @@ class PhraseTest extends \PHPUnit_Framework_TestCase */ protected $rendererMock; - /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager - */ - protected $objectManager; - /** * SetUp method * @@ -34,7 +29,6 @@ class PhraseTest extends \PHPUnit_Framework_TestCase $this->defaultRenderer = Phrase::getRenderer(); $this->rendererMock = $this->getMockBuilder('Magento\Framework\Phrase\RendererInterface') ->getMock(); - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); } /** @@ -57,10 +51,7 @@ class PhraseTest extends \PHPUnit_Framework_TestCase $text = 'some text'; $arguments = ['arg1', 'arg2']; $result = 'rendered text'; - $phrase = $this->objectManager->getObject('Magento\Framework\Phrase', [ - 'text' => $text, - 'arguments' => $arguments, - ]); + $phrase = new Phrase($text, $arguments); Phrase::setRenderer($this->rendererMock); $this->rendererMock->expects($this->once()) @@ -81,9 +72,7 @@ class PhraseTest extends \PHPUnit_Framework_TestCase $this->rendererMock->expects($this->never()) ->method('render'); - $this->objectManager->getObject('Magento\Framework\Phrase', [ - 'text' => 'some text', - ]); + new Phrase('some text'); } /** @@ -96,10 +85,7 @@ class PhraseTest extends \PHPUnit_Framework_TestCase $text = 'some text'; $arguments = ['arg1', 'arg2']; $result = 'rendered text'; - $phrase = $this->objectManager->getObject('Magento\Framework\Phrase', [ - 'text' => $text, - 'arguments' => $arguments, - ]); + $phrase = new Phrase($text, $arguments); Phrase::setRenderer($this->rendererMock); $this->rendererMock->expects($this->once()) @@ -119,9 +105,6 @@ class PhraseTest extends \PHPUnit_Framework_TestCase { $text = 'some text'; $phrase = new Phrase($text); - $phrase = $this->objectManager->getObject('Magento\Framework\Phrase', [ - 'text' => $text, - ]); $this->assertEquals($text, $phrase->getText()); } @@ -135,36 +118,31 @@ class PhraseTest extends \PHPUnit_Framework_TestCase { $text = 'some text'; $arguments = ['arg1', 'arg2']; - $phrase1 = $this->objectManager->getObject('Magento\Framework\Phrase', [ - 'text' => $text, - ]); - $phrase2 = $this->objectManager->getObject('Magento\Framework\Phrase', [ - 'text' => $text, - 'arguments' => $arguments, - ]); + $phrase1 = new Phrase($text); + $phrase2 = new Phrase($text, $arguments); $this->assertEquals([], $phrase1->getArguments()); $this->assertEquals($arguments, $phrase2->getArguments()); } + public function testToStringWithExceptionOnRender() + { + $text = 'raw text'; + $exception = new \Exception('something went wrong'); + $phrase = new Phrase($text); + + $this->rendererMock->expects($this->any()) + ->method('render') + ->willThrowException($exception); + + $this->assertEquals($text, (string)$phrase); + } + /** - * Test default rendering - * - * @return void + * Test default renderer */ - public function testDefaultRendering() + public function testDefaultRenderer() { - $text = 'parameter1 is replaced by %1 parameter2 is replaced by %2'; - $arguments = ['arg1', 'arg2']; - $result = 'parameter1 is replaced by arg1 parameter2 is replaced by arg2'; - $phrase = $this->objectManager->getObject('Magento\Framework\Phrase', [ - 'text' => $text, - 'arguments' => $arguments, - ]); - - $this->assertEquals($text, $phrase->getText()); - $this->assertEquals($arguments, $phrase->getArguments()); - $this->assertTrue($phrase->getRenderer() instanceof \Magento\Framework\Phrase\Renderer\Placeholder); - $this->assertEquals($result, $phrase->render()); + $this->assertInstanceOf('Magento\Framework\Phrase\Renderer\Placeholder', Phrase::getRenderer()); } } diff --git a/lib/internal/Magento/Framework/Test/Unit/UrlTest.php b/lib/internal/Magento/Framework/Test/Unit/UrlTest.php index 46d9a13f0bf0a5290fd6086d78aab72a9bf502ca..69e2260002ce05ff621e5b63baf613c7e30a879b 100644 --- a/lib/internal/Magento/Framework/Test/Unit/UrlTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/UrlTest.php @@ -73,9 +73,10 @@ class UrlTest extends \PHPUnit_Framework_TestCase } /** + * @param bool $resolve * @return \Magento\Framework\Url\RouteParamsResolverFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected function getRouteParamsResolver() + protected function getRouteParamsResolverFactory($resolve = true) { $routeParamsResolverFactoryMock = $this->getMock( 'Magento\Framework\Url\RouteParamsResolverFactory', @@ -84,8 +85,10 @@ class UrlTest extends \PHPUnit_Framework_TestCase '', false ); - $routeParamsResolverFactoryMock->expects($this->once())->method('create') - ->will($this->returnValue($this->routeParamsResolverMock)); + if ($resolve) { + $routeParamsResolverFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($this->routeParamsResolverMock)); + } return $routeParamsResolverFactoryMock; } @@ -152,7 +155,10 @@ class UrlTest extends \PHPUnit_Framework_TestCase public function testGetBaseUrlNotLinkType() { $model = $this->getUrlModel( - ['scopeResolver' => $this->scopeResolverMock, 'routeParamsResolver' => $this->getRouteParamsResolver()] + [ + 'scopeResolver' => $this->scopeResolverMock, + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory() + ] ); $baseUrl = 'base-url'; @@ -184,9 +190,12 @@ class UrlTest extends \PHPUnit_Framework_TestCase $requestMock = $this->getRequestMock(); $routeConfigMock = $this->getMock('Magento\Framework\App\Route\ConfigInterface'); $model = $this->getUrlModel( - ['scopeResolver' => $this->scopeResolverMock, 'routeParamsResolver' => $this->getRouteParamsResolver(), + [ + 'scopeResolver' => $this->scopeResolverMock, + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'queryParamsResolver' => $this->queryParamsResolverMock, - 'request' => $requestMock, 'routeConfig' => $routeConfigMock, ] + 'request' => $requestMock, 'routeConfig' => $routeConfigMock, + ] ); $baseUrl = 'http://localhost/index.php/'; @@ -218,7 +227,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase { $model = $this->getUrlModel([ 'scopeResolver' => $this->scopeResolverMock, - 'routeParamsResolver' => $this->getRouteParamsResolver(), + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), ]); $model->setData('route_path', 'catalog/product/view'); @@ -233,7 +242,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase { $model = $this->getUrlModel([ 'scopeResolver' => $this->scopeResolverMock, - 'routeParamsResolver' => $this->getRouteParamsResolver(), + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'request' => $this->getRequestMock() ]); $model->setData('route_name', 'catalog'); @@ -251,7 +260,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue(['foo' => 'bar', 'true' => false])); $model = $this->getUrlModel([ 'scopeResolver' => $this->scopeResolverMock, - 'routeParamsResolver' => $this->getRouteParamsResolver(), + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'request' => $this->getRequestMock() ]); @@ -270,7 +279,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase $request->expects($this->once())->method('getAlias')->will($this->returnValue('/catalog/product/view/')); $model = $this->getUrlModel([ 'scopeResolver' => $this->scopeResolverMock, - 'routeParamsResolver' => $this->getRouteParamsResolver(), + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'request' => $request, ]); @@ -299,9 +308,12 @@ class UrlTest extends \PHPUnit_Framework_TestCase $requestMock = $this->getRequestMock(); $routeConfigMock = $this->getMock('Magento\Framework\App\Route\ConfigInterface'); $model = $this->getUrlModel( - ['scopeResolver' => $this->scopeResolverMock, 'routeParamsResolver' => $this->getRouteParamsResolver(), + [ + 'scopeResolver' => $this->scopeResolverMock, + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'queryParamsResolver' => $this->queryParamsResolverMock, - 'request' => $requestMock, 'routeConfig' => $routeConfigMock, ] + 'request' => $requestMock, 'routeConfig' => $routeConfigMock, + ] ); $baseUrl = 'http://localhost/index.php/'; @@ -332,9 +344,12 @@ class UrlTest extends \PHPUnit_Framework_TestCase $requestMock = $this->getRequestMock(); $routeConfigMock = $this->getMock('Magento\Framework\App\Route\ConfigInterface'); $model = $this->getUrlModel( - ['scopeResolver' => $this->scopeResolverMock, 'routeParamsResolver' => $this->getRouteParamsResolver(), + [ + 'scopeResolver' => $this->scopeResolverMock, + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'queryParamsResolver' => $this->queryParamsResolverMock, - 'request' => $requestMock, 'routeConfig' => $routeConfigMock, ] + 'request' => $requestMock, 'routeConfig' => $routeConfigMock, + ] ); $baseUrl = 'http://localhost/index.php/'; @@ -363,7 +378,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase 'request' => $requestMock, 'sidResolver' => $this->sidResolverMock, 'scopeResolver' => $this->scopeResolverMock, - 'routeParamsResolver' => $this->getRouteParamsResolver(), + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(false), 'queryParamsResolver' => $this->queryParamsResolverMock, ]); @@ -376,8 +391,12 @@ class UrlTest extends \PHPUnit_Framework_TestCase public function testGetRedirectUrl() { $model = $this->getUrlModel( - ['routeParamsResolver' => $this->getRouteParamsResolver(), 'session' => $this->sessionMock, - 'sidResolver' => $this->sidResolverMock, 'queryParamsResolver' => $this->queryParamsResolverMock, ] + [ + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), + 'session' => $this->sessionMock, + 'sidResolver' => $this->sidResolverMock, + 'queryParamsResolver' => $this->queryParamsResolverMock, + ] ); $this->sidResolverMock->expects($this->once())->method('getUseSessionInUrl')->will($this->returnValue(true)); @@ -396,8 +415,12 @@ class UrlTest extends \PHPUnit_Framework_TestCase public function testGetRedirectUrlWithSessionId() { $model = $this->getUrlModel( - ['routeParamsResolver' => $this->getRouteParamsResolver(), 'session' => $this->sessionMock, - 'sidResolver' => $this->sidResolverMock, 'queryParamsResolver' => $this->queryParamsResolverMock, ] + [ + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(false), + 'session' => $this->sessionMock, + 'sidResolver' => $this->sidResolverMock, + 'queryParamsResolver' => $this->queryParamsResolverMock, + ] ); $this->sidResolverMock->expects($this->once())->method('getUseSessionInUrl')->will($this->returnValue(true)); @@ -422,7 +445,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase public function testGetRouteUrlWithValidUrl() { - $model = $this->getUrlModel(['routeParamsResolver' => $this->getRouteParamsResolver()]); + $model = $this->getUrlModel(['routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(false)]); $this->routeParamsResolverMock->expects($this->never())->method('unsetData'); $this->assertEquals('http://example.com', $model->getRouteUrl('http://example.com')); @@ -485,7 +508,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase $urlSecurityInfoMock = $this->getMock('Magento\Framework\Url\SecurityInfoInterface'); $model = $this->getUrlModel([ 'urlSecurityInfo' => $urlSecurityInfoMock, - 'routeParamsResolver' => $this->getRouteParamsResolver(), + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'scopeResolver' => $this->scopeResolverMock, 'scopeConfig' => $this->scopeConfig, ]); @@ -530,7 +553,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase public function testGetConfigDataWithSecureIsForcedParam() { $model = $this->getUrlModel([ - 'routeParamsResolver' => $this->getRouteParamsResolver(), + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), 'scopeResolver' => $this->scopeResolverMock, 'scopeConfig' => $this->scopeConfig, ]); @@ -562,8 +585,13 @@ class UrlTest extends \PHPUnit_Framework_TestCase { $requestMock = $this->getRequestMock(); $model = $this->getUrlModel( - ['session' => $this->sessionMock, 'request' => $requestMock, 'sidResolver' => $this->sidResolverMock, - 'scopeResolver' => $this->scopeResolverMock, 'routeParamsResolver' => $this->getRouteParamsResolver(), ] + [ + 'session' => $this->sessionMock, + 'request' => $requestMock, + 'sidResolver' => $this->sidResolverMock, + 'scopeResolver' => $this->scopeResolverMock, + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), + ] ); $requestMock->expects($this->once()) @@ -585,8 +613,13 @@ class UrlTest extends \PHPUnit_Framework_TestCase { $requestMock = $this->getRequestMock(); $model = $this->getUrlModel( - ['session' => $this->sessionMock, 'request' => $requestMock, 'sidResolver' => $this->sidResolverMock, - 'scopeResolver' => $this->scopeResolverMock, 'routeParamsResolver' => $this->getRouteParamsResolver(), ] + [ + 'session' => $this->sessionMock, + 'request' => $requestMock, + 'sidResolver' => $this->sidResolverMock, + 'scopeResolver' => $this->scopeResolverMock, + 'routeParamsResolverFactory' => $this->getRouteParamsResolverFactory(), + ] ); $requestMock->expects($this->once())->method('getHttpHost')->will($this->returnValue('localhost')); diff --git a/lib/internal/Magento/Framework/Url.php b/lib/internal/Magento/Framework/Url.php index efffc744e3fe46da126f655f16a95c9f1c5bd4a7..697e461df050f1f623075655acd3ea4fc13ccaa9 100644 --- a/lib/internal/Magento/Framework/Url.php +++ b/lib/internal/Magento/Framework/Url.php @@ -56,6 +56,7 @@ namespace Magento\Framework; * - G: route_path * - H: route_url * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInterface { @@ -133,8 +134,12 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt /** * @var \Magento\Framework\Url\RouteParamsResolverInterface */ - protected $_routeParamsResolver; + private $_routeParamsResolver; + /** + * @var \Magento\Framework\Url\RouteParamsResolverFactory + */ + private $_routeParamsResolverFactory; /** * @var \Magento\Framework\Url\ScopeResolverInterface */ @@ -157,7 +162,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt * @param \Magento\Framework\Url\ScopeResolverInterface $scopeResolver * @param \Magento\Framework\Session\Generic $session * @param \Magento\Framework\Session\SidResolverInterface $sidResolver - * @param \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolver + * @param \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory * @param \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param string $scopeType @@ -171,7 +176,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt \Magento\Framework\Url\ScopeResolverInterface $scopeResolver, \Magento\Framework\Session\Generic $session, \Magento\Framework\Session\SidResolverInterface $sidResolver, - \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolver, + \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory, \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, $scopeType, @@ -183,7 +188,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt $this->_scopeResolver = $scopeResolver; $this->_session = $session; $this->_sidResolver = $sidResolver; - $this->_routeParamsResolver = $routeParamsResolver->create(); + $this->_routeParamsResolverFactory = $routeParamsResolverFactory; $this->_queryParamsResolver = $queryParamsResolver; $this->_scopeConfig = $scopeConfig; $this->_scopeType = $scopeType; @@ -322,10 +327,10 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt */ protected function _getType() { - if (!$this->_routeParamsResolver->hasData('type')) { - $this->_routeParamsResolver->setData('type', self::DEFAULT_URL_TYPE); + if (!$this->getRouteParamsResolver()->hasData('type')) { + $this->getRouteParamsResolver()->setData('type', self::DEFAULT_URL_TYPE); } - return $this->_routeParamsResolver->getType(); + return $this->getRouteParamsResolver()->getType(); } /** @@ -335,27 +340,27 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt */ protected function _isSecure() { - if ($this->_routeParamsResolver->hasData('secure_is_forced')) { - return (bool) $this->_routeParamsResolver->getData('secure'); + if ($this->getRouteParamsResolver()->hasData('secure_is_forced')) { + return (bool) $this->getRouteParamsResolver()->getData('secure'); } if (!$this->_getScope()->isUrlSecure()) { return false; } - if (!$this->_routeParamsResolver->hasData('secure')) { + if (!$this->getRouteParamsResolver()->hasData('secure')) { if ($this->_getType() == UrlInterface::URL_TYPE_LINK) { $pathSecure = $this->_urlSecurityInfo->isSecure('/' . $this->_getActionPath()); - $this->_routeParamsResolver->setData('secure', $pathSecure); + $this->getRouteParamsResolver()->setData('secure', $pathSecure); } elseif ($this->_getType() == UrlInterface::URL_TYPE_STATIC) { $isRequestSecure = $this->_getRequest()->isSecure(); - $this->_routeParamsResolver->setData('secure', $isRequestSecure); + $this->getRouteParamsResolver()->setData('secure', $isRequestSecure); } else { - $this->_routeParamsResolver->setData('secure', true); + $this->getRouteParamsResolver()->setData('secure', true); } } - return $this->_routeParamsResolver->getData('secure'); + return $this->getRouteParamsResolver()->getData('secure'); } /** @@ -367,7 +372,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt public function setScope($params) { $this->setData('scope', $this->_scopeResolver->getScope($params)); - $this->_routeParamsResolver->setScope($this->_scopeResolver->getScope($params)); + $this->getRouteParamsResolver()->setScope($this->_scopeResolver->getScope($params)); return $this; } @@ -401,11 +406,11 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt $this->setScope($params['_scope']); } if (isset($params['_type'])) { - $this->_routeParamsResolver->setType($params['_type']); + $this->getRouteParamsResolver()->setType($params['_type']); } if (isset($params['_secure'])) { - $this->_routeParamsResolver->setSecure($params['_secure']); + $this->getRouteParamsResolver()->setSecure($params['_secure']); } /** @@ -416,13 +421,13 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt $this->_getRouteFrontName() ) ) { - $this->_routeParamsResolver->setType(UrlInterface::URL_TYPE_DIRECT_LINK); + $this->getRouteParamsResolver()->setType(UrlInterface::URL_TYPE_DIRECT_LINK); } $result = $this->_getScope()->getBaseUrl($this->_getType(), $this->_isSecure()); // setting back the original scope $this->setScope($origScope); - $this->_routeParamsResolver->setType(self::DEFAULT_URL_TYPE); + $this->getRouteParamsResolver()->setType(self::DEFAULT_URL_TYPE); return $result; } @@ -471,7 +476,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt $key = array_shift($routePieces); if (!empty($routePieces)) { $value = array_shift($routePieces); - $this->_routeParamsResolver->setRouteParam($key, $value); + $this->getRouteParamsResolver()->setRouteParam($key, $value); } } } @@ -650,7 +655,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt */ protected function _setRouteParams(array $data, $unsetOldParams = true) { - $this->_routeParamsResolver->setRouteParams($data, $unsetOldParams); + $this->getRouteParamsResolver()->setRouteParams($data, $unsetOldParams); return $this; } @@ -661,7 +666,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt */ protected function _getRouteParams() { - return $this->_routeParamsResolver->getRouteParams(); + return $this->getRouteParamsResolver()->getRouteParams(); } /** @@ -677,7 +682,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt return $routePath; } - $this->_routeParamsResolver->unsetData('route_params'); + $this->getRouteParamsResolver()->unsetData('route_params'); if (isset($routeParams['_direct'])) { if (is_array($routeParams)) { @@ -786,7 +791,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt * this method has condition for adding default controller and action names * in case when we have params */ - $this->_routeParamsResolver->unsetData('secure'); + $this->getRouteParamsResolver()->unsetData('secure'); $fragment = null; if (isset($routeParams['_fragment'])) { $fragment = $routeParams['_fragment']; @@ -840,7 +845,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt if (!is_null($fragment)) { $url .= '#' . $fragment; } - $this->_routeParamsResolver->unsetData('secure'); + $this->getRouteParamsResolver()->unsetData('secure'); return $this->escape($url); } @@ -1038,4 +1043,17 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt $url = $this->_request->getScheme() . '://' . $this->_request->getHttpHost() . $port . $requestUri; return $url; } + + /** + * Get Route Params Resolver + * + * @return Url\RouteParamsResolverInterface + */ + protected function getRouteParamsResolver() + { + if (!$this->_routeParamsResolver) { + $this->_routeParamsResolver = $this->_routeParamsResolverFactory->create(); + } + return $this->_routeParamsResolver; + } } diff --git a/lib/internal/Magento/Framework/Url/ScopeResolverInterface.php b/lib/internal/Magento/Framework/Url/ScopeResolverInterface.php index 893443659220d4b68e5ec3514f25beb0ea3c7725..a31ae25c76ea41a6efea88d85ccfb5c424092143 100644 --- a/lib/internal/Magento/Framework/Url/ScopeResolverInterface.php +++ b/lib/internal/Magento/Framework/Url/ScopeResolverInterface.php @@ -10,7 +10,7 @@ interface ScopeResolverInterface extends \Magento\Framework\App\ScopeResolverInt /** * Retrieve area code * - * @return \Magento\Framework\Url\ScopeInterface[] + * @return string|null */ public function getAreaCode(); } diff --git a/lib/internal/Magento/Framework/UrlInterface/Proxy.php b/lib/internal/Magento/Framework/UrlInterface/Proxy.php new file mode 100644 index 0000000000000000000000000000000000000000..7ed1a1bbc7bff3df6959ec70ed2aa2c779b21636 --- /dev/null +++ b/lib/internal/Magento/Framework/UrlInterface/Proxy.php @@ -0,0 +1,212 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\UrlInterface; + +/** + * Proxy class for @see \Magento\Framework\UrlInterface + */ +class Proxy implements \Magento\Framework\UrlInterface +{ + /** + * Object Manager instance + * + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $_objectManager = null; + + /** + * Proxied instance name + * + * @var string + */ + protected $_instanceName = null; + + /** + * Proxied instance + * + * @var \Magento\Framework\UrlInterface + */ + protected $_subject = null; + + /** + * Instance shareability flag + * + * @var bool + */ + protected $_isShared = null; + + /** + * Proxy constructor + * + * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param string $instanceName + * @param bool $shared + */ + public function __construct( + \Magento\Framework\ObjectManagerInterface $objectManager, + $instanceName = '\\Magento\\Framework\\UrlInterface', + $shared = true + ) { + $this->_objectManager = $objectManager; + $this->_instanceName = $instanceName; + $this->_isShared = $shared; + } + + /** + * @return array + */ + public function __sleep() + { + return ['_subject', '_isShared']; + } + + /** + * Retrieve ObjectManager from global scope + * + * @return void + */ + public function __wakeup() + { + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + } + + /** + * Clone proxied instance + * + * @return void + */ + public function __clone() + { + $this->_subject = clone $this->_getSubject(); + } + + /** + * Get proxied instance + * + * @return \Magento\Framework\UrlInterface + */ + protected function _getSubject() + { + if (!$this->_subject) { + $this->_subject = true === $this->_isShared + ? $this->_objectManager->get($this->_instanceName) + : $this->_objectManager->create($this->_instanceName); + } + return $this->_subject; + } + + /** + * {@inheritdoc} + */ + public function getUseSession() + { + return $this->_getSubject()->getUseSession(); + } + + /** + * {@inheritdoc} + */ + public function getBaseUrl($params = []) + { + return $this->_getSubject()->getBaseUrl($params); + } + + /** + * {@inheritdoc} + */ + public function getCurrentUrl() + { + return $this->_getSubject()->getCurrentUrl(); + } + + /** + * {@inheritdoc} + */ + public function getRouteUrl($routePath = null, $routeParams = null) + { + return $this->_getSubject()->getRouteUrl($routePath, $routeParams); + } + + /** + * {@inheritdoc} + */ + public function addSessionParam() + { + return $this->_getSubject()->addSessionParam(); + } + + /** + * {@inheritdoc} + */ + public function addQueryParams(array $data) + { + return $this->_getSubject()->addQueryParams($data); + } + + /** + * {@inheritdoc} + */ + public function setQueryParam($key, $data) + { + return $this->_getSubject()->setQueryParam($key, $data); + } + + /** + * {@inheritdoc} + */ + public function getUrl($routePath = null, $routeParams = null) + { + return $this->_getSubject()->getUrl($routePath, $routeParams); + } + + /** + * {@inheritdoc} + */ + public function escape($value) + { + return $this->_getSubject()->escape($value); + } + + /** + * {@inheritdoc} + */ + public function getDirectUrl($url, $params = []) + { + return $this->_getSubject()->getDirectUrl($url, $params); + } + + /** + * {@inheritdoc} + */ + public function sessionUrlVar($html) + { + return $this->_getSubject()->sessionUrlVar($html); + } + + /** + * {@inheritdoc} + */ + public function isOwnOriginUrl() + { + return $this->_getSubject()->isOwnOriginUrl(); + } + + /** + * {@inheritdoc} + */ + public function getRedirectUrl($url) + { + return $this->_getSubject()->getRedirectUrl($url); + } + + /** + * {@inheritdoc} + */ + public function setScope($params) + { + return $this->_getSubject()->setScope($params); + } +} diff --git a/lib/internal/Magento/Framework/Validator/Factory.php b/lib/internal/Magento/Framework/Validator/Factory.php index a663b91cc745f01f164e1d30a1f6e9f04682087b..ef5679b220c2460dbc1e94d7d09760af0436fa31 100644 --- a/lib/internal/Magento/Framework/Validator/Factory.php +++ b/lib/internal/Magento/Framework/Validator/Factory.php @@ -24,6 +24,11 @@ class Factory */ protected $_configFiles = null; + /** + * @var bool + */ + private $isDefaultTranslatorInitialized = false; + /** * Initialize dependencies * @@ -36,7 +41,6 @@ class Factory ) { $this->_objectManager = $objectManager; $this->_configFiles = $moduleReader->getConfigurationFiles('validation.xml'); - $this->_initializeDefaultTranslator(); } /** @@ -46,15 +50,18 @@ class Factory */ protected function _initializeDefaultTranslator() { - // Pass translations to \Magento\Framework\TranslateInterface from validators - $translatorCallback = function () { - $argc = func_get_args(); - return (string)new \Magento\Framework\Phrase(array_shift($argc), $argc); - }; - /** @var \Magento\Framework\Translate\Adapter $translator */ - $translator = $this->_objectManager->create('Magento\Framework\Translate\Adapter'); - $translator->setOptions(['translator' => $translatorCallback]); - \Magento\Framework\Validator\AbstractValidator::setDefaultTranslator($translator); + if (!$this->isDefaultTranslatorInitialized) { + // Pass translations to \Magento\Framework\TranslateInterface from validators + $translatorCallback = function () { + $argc = func_get_args(); + return (string)new \Magento\Framework\Phrase(array_shift($argc), $argc); + }; + /** @var \Magento\Framework\Translate\Adapter $translator */ + $translator = $this->_objectManager->create('Magento\Framework\Translate\Adapter'); + $translator->setOptions(['translator' => $translatorCallback]); + \Magento\Framework\Validator\AbstractValidator::setDefaultTranslator($translator); + $this->isDefaultTranslatorInitialized = true; + } } /** @@ -66,6 +73,7 @@ class Factory */ public function getValidatorConfig() { + $this->_initializeDefaultTranslator(); return $this->_objectManager->create('Magento\Framework\Validator\Config', ['configFiles' => $this->_configFiles]); } @@ -79,6 +87,7 @@ class Factory */ public function createValidatorBuilder($entityName, $groupName, array $builderConfig = null) { + $this->_initializeDefaultTranslator(); return $this->getValidatorConfig()->createValidatorBuilder($entityName, $groupName, $builderConfig); } @@ -92,6 +101,7 @@ class Factory */ public function createValidator($entityName, $groupName, array $builderConfig = null) { + $this->_initializeDefaultTranslator(); return $this->getValidatorConfig()->createValidator($entityName, $groupName, $builderConfig); } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Argument/Interpreter/ConfigurableObject.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Argument/Interpreter/ConfigurableObject.php new file mode 100644 index 0000000000000000000000000000000000000000..f2d2779be11166b93310f688199c584c3b63c44f --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Argument/Interpreter/ConfigurableObject.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Argument\Interpreter; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Data\Argument\InterpreterInterface; + +/** + * Class ConfigurableObject + */ +class ConfigurableObject implements InterpreterInterface +{ + /** + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * @var InterpreterInterface + */ + protected $argumentInterpreter; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + * @param InterpreterInterface $argumentInterpreter + */ + public function __construct(ObjectManagerInterface $objectManager, InterpreterInterface $argumentInterpreter) + { + $this->objectManager = $objectManager; + $this->argumentInterpreter = $argumentInterpreter; + } + + /** + * {@inheritdoc} + */ + public function evaluate(array $data) + { + if (!isset($data['argument'])) { + throw new \InvalidArgumentException('Node "argument" required for this type.'); + } + foreach ($data['argument'] as $name => $argument) { + $arguments[$name] = $this->argumentInterpreter->evaluate($argument); + } + if (!isset($arguments['class'])) { + throw new \InvalidArgumentException('Node "argument" with name "class" is required for this type.'); + } + $className = $arguments['class']; + unset($arguments['class']); + + return $this->objectManager->create($className, $arguments); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..64c4cffc8cb596e60697e245c36ef9e526284f3f --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent; + +/** + * Class ArrayObjectFactory + */ +class ArrayObjectFactory +{ + /** + * Create class instance with specified parameters + * + * @param array $data + * @return \ArrayObject + */ + public function create(array $data = []) + { + return new \ArrayObject($data); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Converter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Converter.php new file mode 100644 index 0000000000000000000000000000000000000000..bf13c675696839882895b842a4e2b2252e64ff5f --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Converter.php @@ -0,0 +1,123 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +use Magento\Framework\Config\ConverterInterface; +use Magento\Framework\View\Layout\Argument\Parser; + +/** + * Class Converter + */ +class Converter implements ConverterInterface +{ + /** + * The key attributes of a node + */ + const DATA_ATTRIBUTES_KEY = '@attributes'; + + /** + * The key for the data arguments + */ + const DATA_ARGUMENTS_KEY = '@arguments'; + + /** + * The key of the argument node + */ + const ARGUMENT_KEY = 'argument'; + + /** + * Key name attribute value + */ + const NAME_ATTRIBUTE_KEY = 'name'; + + /** + * @var Parser + */ + protected $argumentParser; + + /** + * Constructor + * + * @param Parser $argumentParser + */ + public function __construct(Parser $argumentParser) + { + $this->argumentParser = $argumentParser; + } + + /** + * Transform Xml to array + * + * @param \DOMNode $node + * @return array|string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function toArray(\DOMNode $node) + { + $result = []; + $attributes = []; + // Collect data from attributes + if ($node->hasAttributes()) { + foreach ($node->attributes as $attribute) { + $attributes[$attribute->name] = $attribute->value; + } + } + switch ($node->nodeType) { + case XML_TEXT_NODE: + case XML_COMMENT_NODE: + case XML_CDATA_SECTION_NODE: + break; + default: + if ($node->localName === static::ARGUMENT_KEY) { + if (!isset($attributes[static::NAME_ATTRIBUTE_KEY])) { + throw new \InvalidArgumentException( + 'Attribute "' . static::NAME_ATTRIBUTE_KEY . '" is absent in the attributes node.' + ); + } + $result[ $attributes[static::NAME_ATTRIBUTE_KEY] ] = $this->argumentParser->parse($node); + } else { + $arguments = []; + for ($i = 0, $iLength = $node->childNodes->length; $i < $iLength; ++$i) { + $itemNode = $node->childNodes->item($i); + if (empty($itemNode->localName)) { + continue; + } + if ($itemNode->nodeName === static::ARGUMENT_KEY) { + $arguments += $this->toArray($itemNode); + } else { + $result[$itemNode->localName][] = $this->toArray($itemNode); + } + } + if (!empty($arguments)) { + $result[static::DATA_ARGUMENTS_KEY] = $arguments; + } + if (!empty($attributes)) { + $result[static::DATA_ATTRIBUTES_KEY] = $attributes; + } + } + break; + } + + return $result; + } + + /** + * Convert configuration + * + * @param \DOMDocument|null $source + * @return array + */ + public function convert($source) + { + if ($source === null) { + return []; + } + + return $this->toArray($source); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMerger.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMerger.php new file mode 100644 index 0000000000000000000000000000000000000000..72b18bb610577f7218ef4615f0d7cde0cf3d421e --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMerger.php @@ -0,0 +1,455 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +use Magento\Framework\Config\Dom; +use Magento\Framework\Module\Dir\Reader as DirectoryReader; + +/** + * Class DomMerger + */ +class DomMerger implements DomMergerInterface +{ + /** + * Format of items in errors array to be used by default. Available placeholders - fields of \LibXMLError. + */ + const ERROR_FORMAT_DEFAULT = "Message: %message%\nLine: %line%\n"; + + /** + * Location schema file + * + * @var string + */ + protected $schemaFilePath; + + /** + * Result DOM document + * + * @var \DOMDocument + */ + protected $domDocument; + + /** + * Id attribute list + * + * @var array + */ + protected $idAttributes = []; + + /** + * Context XPath + * + * @var array + */ + protected $contextXPath = []; + + /** + * Is merge simple XML Element + * + * @var bool + */ + protected $isMergeSimpleXMLElement; + + /** + * Build DOM with initial XML contents and specifying identifier attributes for merging + * + * Format of $schemaFileType: array('etc', 'sql', 'data', 'i18n', 'view', 'Controller') + * Format of $schemaFileModule: 'Magento_XXXXX' + * Format of $schemaFileName: 'schema.xsd' + * Format of $idAttributes: array('name', 'id') + * Format of $contextXPath: array('/config/ui') + * The path to ID attribute name should not include any attribute notations or modifiers -- only node names + * + * @param string $schemaFileType + * @param string $schemaFileModule + * @param string $schemaFileName + * @param DirectoryReader $directoryReader + * @param bool $isMergeSimpleXMLElement + * @param array $contextXPath + * @param array $idAttributes + */ + public function __construct( + DirectoryReader $directoryReader, + $schemaFileType, + $schemaFileModule, + $schemaFileName, + $isMergeSimpleXMLElement = false, + array $contextXPath = [], + array $idAttributes = [] + ) { + $this->schemaFilePath = $directoryReader->getModuleDir($schemaFileType, $schemaFileModule) . '/' + . trim($schemaFileName, '/'); + $this->isMergeSimpleXMLElement = $isMergeSimpleXMLElement; + $this->contextXPath = $contextXPath; + $this->idAttributes = $idAttributes; + } + + /** + * Is id attribute + * + * @param string $attributeName + * @return bool + */ + protected function isIdAttribute($attributeName) + { + return in_array($attributeName, $this->idAttributes); + } + + /** + * Is merge context + * + * @param string $xPath + * @return bool + */ + protected function isMergeContext($xPath) + { + foreach ($this->contextXPath as $context) { + if (strpos($xPath, $context) === 0) { + return true; + } + } + return false; + } + + /** + * Is context XPath + * + * @param array $xPath + * @return bool + */ + protected function isContextXPath(array $xPath) + { + return count(array_intersect($xPath, $this->contextXPath)) === count($xPath); + } + + /** + * Merges attributes of the merge node to the base node + * + * @param \DOMElement $baseNode + * @param \DOMNode $mergeNode + * @return void + */ + protected function mergeAttributes(\DOMElement $baseNode, \DOMNode $mergeNode) + { + foreach ($mergeNode->attributes as $name => $attribute) { + $baseNode->setAttribute($name, $attribute->value); + } + } + + /** + * Create XPath + * + * @param \DOMNode $node + * @return string + */ + protected function createXPath(\DOMNode $node) + { + $parentXPath = ''; + $currentXPath = $node->getNodePath(); + if ($node->parentNode !== null && !$node->isSameNode($node->parentNode)) { + $parentXPath = $this->createXPath($node->parentNode); + $pathParts = explode('/', $currentXPath); + $currentXPath = '/' . end($pathParts); + } + $attributesXPath = ''; + if ($node->hasAttributes()) { + $attributes = []; + foreach ($node->attributes as $name => $attribute) { + if ($this->isIdAttribute($name)) { + $attributes[] = sprintf('@%s="%s"', $name, $attribute->value); + break; + } + } + if (!empty($attributes)) { + if (substr($currentXPath, -1) === ']') { + $currentXPath = substr($currentXPath, 0, strrpos($currentXPath, '[')); + } + $attributesXPath = '[' . implode(' and ', $attributes) . ']'; + } + } + return '/' . trim($parentXPath . $currentXPath . $attributesXPath, '/'); + } + + /** + * Merge nested xml nodes + * + * @param \DOMXPath $rootDomXPath + * @param \DOMNodeList $insertedNodes + * @param \DOMNode $contextNode + * @return void + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function nestedMerge(\DOMXPath $rootDomXPath, \DOMNodeList $insertedNodes, \DOMNode $contextNode) + { + for ($i = 0, $iLength = $insertedNodes->length; $i < $iLength; ++$i) { + $insertedItem = $insertedNodes->item($i); + switch ($insertedItem->nodeType) { + case XML_TEXT_NODE: + case XML_COMMENT_NODE: + case XML_CDATA_SECTION_NODE: + if (trim($insertedItem->textContent) !== '') { + $this->insertBefore($contextNode, $insertedItem); + } + break; + default: + $insertedXPath = $this->createXPath($insertedItem); + $rootMatchList = $rootDomXPath->query($insertedXPath, $contextNode); + $jLength = $rootMatchList->length; + if ($jLength > 0) { + for ($j = 0; $j < $jLength; ++$j) { + $rootItem = $rootMatchList->item($j); + $rootItemXPath = $this->createXPath($rootItem); + if ($this->isMergeContext($insertedXPath)) { + if ($this->isTextNode($insertedItem) && $this->isTextNode($rootItem)) { + $rootItem->nodeValue = $insertedItem->nodeValue; + } else if (!$this->isContextXPath([$rootItemXPath, $insertedXPath]) + && !$this->hasIdAttribute($rootItem) + && !$this->hasIdAttribute($insertedItem) + ) { + if ($this->isMergeSimpleXMLElement) { + $this->nestedMerge($rootDomXPath, $insertedItem->childNodes, $rootItem); + $this->mergeAttributes($rootItem, $insertedItem); + } else { + $this->appendChild($contextNode, $insertedItem); + } + } else { + $this->nestedMerge($rootDomXPath, $insertedItem->childNodes, $rootItem); + $this->mergeAttributes($rootItem, $insertedItem); + } + } else { + $this->appendChild($contextNode, $insertedItem); + } + } + } else { + $this->appendChild($contextNode, $insertedItem); + } + break; + } + } + } + + /** + * Append child node + * + * @param \DOMNode $parentNode + * @param \DOMNode $childNode + * @return void + */ + protected function appendChild(\DOMNode $parentNode, \DOMNode $childNode) + { + $importNode = $this->getDom()->importNode($childNode, true); + $parentNode->appendChild($importNode); + } + + /** + * Insert before + * + * @param \DOMNode $parentNode + * @param \DOMNode $childNode + * @return void + */ + protected function insertBefore(\DOMNode $parentNode, \DOMNode $childNode) + { + $importNode = $this->getDom()->importNode($childNode, true); + $parentNode->insertBefore($importNode); + } + + /** + * Check if the node content is text + * + * @param \DOMNode $node + * @return bool + */ + protected function isTextNode(\DOMNode $node) + { + return $node->childNodes->length == 1 && $node->childNodes->item(0) instanceof \DOMText; + } + + /** + * Has ID attribute + * + * @param \DOMNode $node + * @return bool + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + protected function hasIdAttribute(\DOMNode $node) + { + if (!$node->hasAttributes()) { + return false; + } + + foreach ($node->attributes as $name => $attribute) { + if (in_array($name, $this->idAttributes)) { + return true; + } + } + + return false; + } + + /** + * Recursive merging of the \DOMElement into the original document + * + * Algorithm: + * 1. Find the same node in original document + * 2. Extend and override original document node attributes and scalar value if found + * 3. Append new node if original document doesn't have the same node + * + * @param \DOMElement $node + * @throws \Magento\Framework\Exception\LocalizedException + * @return void + */ + public function mergeNode(\DOMElement $node) + { + $parentDoom = $this->getDom(); + $this->nestedMerge(new \DOMXPath($parentDoom), $node->childNodes, $parentDoom->documentElement); + } + + /** + * Create DOM document based on $xml parameter + * + * @param string $xml + * @return \DOMDocument + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function createDomDocument($xml) + { + $domDocument = new \DOMDocument(); + $domDocument->loadXML($xml); + if ($this->schemaFilePath) { + $errors = $this->validateDomDocument($domDocument); + if (count($errors)) { + throw new \Magento\Framework\Exception\LocalizedException(implode("\n", $errors)); + } + } + + return $domDocument; + } + + /** + * Validate dom document + * + * @param \DOMDocument $domDocument + * @param string|null $schemaFilePath + * @return array of errors + * @throws \Exception + */ + protected function validateDomDocument(\DOMDocument $domDocument, $schemaFilePath = null) + { + $schemaFilePath = $schemaFilePath !== null ? $schemaFilePath : $this->schemaFilePath; + libxml_use_internal_errors(true); + try { + $result = $domDocument->schemaValidate($schemaFilePath); + $errors = []; + if (!$result) { + $validationErrors = libxml_get_errors(); + if (count($validationErrors)) { + foreach ($validationErrors as $error) { + $errors[] = $this->renderErrorMessage($error, static::ERROR_FORMAT_DEFAULT); + } + } else { + $errors[] = 'Unknown validation error'; + } + } + } catch (\Exception $exception) { + libxml_use_internal_errors(false); + throw $exception; + } + libxml_use_internal_errors(false); + + return $errors; + } + + /** + * Render error message string by replacing placeholders '%field%' with properties of \LibXMLError + * + * @param \LibXMLError $errorInfo + * @return string + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function renderErrorMessage(\LibXMLError $errorInfo) + { + $result = static::ERROR_FORMAT_DEFAULT; + foreach ($errorInfo as $field => $value) { + $result = str_replace('%' . $field . '%', trim((string)$value), $result); + } + if (strpos($result, '%') !== false) { + throw new \Magento\Framework\Exception\LocalizedException( + new \Magento\Framework\Phrase( + 'Error format "' . static::ERROR_FORMAT_DEFAULT . '" contains unsupported placeholders.' + ) + ); + } + + return $result; + } + + /** + * Merge string $xml into DOM document + * + * @param string $xml + * @return void + */ + public function merge($xml) + { + if (!isset($this->domDocument)) { + $this->domDocument = $this->createDomDocument($xml); + } else { + $this->mergeNode($this->createDomDocument($xml)->documentElement); + } + } + + /** + * Get DOM document + * + * @return \DOMDocument + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getDom() + { + if (!isset($this->domDocument)) { + throw new \Magento\Framework\Exception\LocalizedException( + new \Magento\Framework\Phrase('Object DOMDocument should be created.') + ); + } + + return $this->domDocument; + } + + /** + * Set DOM document + * + * @param \DOMDocument $domDocument + * @return void + */ + public function setDom(\DOMDocument $domDocument) + { + $this->domDocument = $domDocument; + } + + /** + * Unset DOM document + * + * @return void + */ + public function unsetDom() + { + unset($this->domDocument); + } + + /** + * Validate self contents towards to specified schema + * + * @param string|null $schemaFilePath + * @return array + */ + public function validate($schemaFilePath = null) + { + return $this->validateDomDocument($this->getDom(), $schemaFilePath); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMergerInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMergerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0fe94609ccebb4fc3c10b20e902d1e5ab49e494c --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMergerInterface.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +/** + * Interface DomMergerInterface + */ +interface DomMergerInterface +{ + /** + * Merge $xml into DOM document + * + * @param string $xml + * @return void + */ + public function merge($xml); + + /** + * Recursive merging of the \DOMElement into the original document + * + * Algorithm: + * 1. Find the same node in original document + * 2. Extend and override original document node attributes and scalar value if found + * 3. Append new node if original document doesn't have the same node + * + * @param \DOMElement $node + * @throws \Magento\Framework\Exception\LocalizedException + * @return void + */ + public function mergeNode(\DOMElement $node); + + /** + * Get DOM document + * + * @return \DOMDocument + */ + public function getDom(); + + /** + * Set DOM document + * + * @param \DOMDocument $domDocument + * @return void + */ + public function setDom(\DOMDocument $domDocument); + + /** + * Unset DOM document + * + * @return void + */ + public function unsetDom(); + + /** + * Validate self contents towards to specified schema + * + * @param string $schemaFileName + * @return array + */ + public function validate($schemaFileName); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php new file mode 100644 index 0000000000000000000000000000000000000000..880b6bc6e1ce75f83cc6dada5ba56a2cc9329a22 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config\FileCollector; + +use Magento\Framework\Filesystem; +use Magento\Framework\View\DesignInterface; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\File\CollectorInterface; +use Magento\Framework\View\Element\UiComponent\Config\FileCollectorInterface; + +/** + * Class AggregatedFileCollector + */ +class AggregatedFileCollector implements FileCollectorInterface +{ + /** + * Search pattern + * + * @var string + */ + protected $searchPattern; + + /** + * @var CollectorInterface + */ + protected $collectorAggregated; + + /** + * @var DesignInterface + */ + protected $design; + + /** + * @var Filesystem + */ + protected $filesystem; + + /** + * Constructor + * + * @param CollectorInterface $collectorAggregated + * @param DesignInterface $design + * @param Filesystem $filesystem + * @param string $searchPattern + */ + public function __construct( + CollectorInterface $collectorAggregated, + DesignInterface $design, + Filesystem $filesystem, + $searchPattern = null + ) { + $this->searchPattern = $searchPattern; + $this->collectorAggregated = $collectorAggregated; + $this->design = $design; + $this->filesystem = $filesystem; + } + + /** + * Collect files + * + * @param string|null $searchPattern + * @return array + * @throws \Exception + */ + public function collectFiles($searchPattern = null) + { + $result = []; + if ($searchPattern === null) { + $searchPattern = $this->searchPattern; + } + if ($searchPattern === null) { + throw new \Exception('Search pattern cannot be empty.'); + } + $files = $this->collectorAggregated->getFiles($this->design->getDesignTheme(), $searchPattern); + $fileReader = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); + foreach ($files as $file) { + $filePath = $fileReader->getRelativePath($file->getFilename()); + $result[sprintf('%x', crc32($filePath))] = $fileReader->readFile($filePath); + } + + return $result; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollectorFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollectorFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..609156211828e0afc6e5f505211e2aea2ed1a766 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollectorFactory.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config\FileCollector; + +use Magento\Framework\ObjectManagerInterface; + +/** + * Class AggregatedFileCollectorFactory + */ +class AggregatedFileCollectorFactory +{ + const INSTANCE_NAME = 'Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollector'; + + /** + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Create config reader + * + * @param array $arguments + * @return AggregatedFileCollector + */ + public function create(array $arguments = []) + { + return $this->objectManager->create(static::INSTANCE_NAME, $arguments); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollectorInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollectorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c2f74254bed42237886c862978d5a7c889c190ba --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollectorInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +/** + * Interface FileCollectorInterface + */ +interface FileCollectorInterface +{ + /** + * Collect files + * + * @param string|null $searchPattern + * @return array + */ + public function collectFiles($searchPattern = null); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Manager.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Manager.php new file mode 100644 index 0000000000000000000000000000000000000000..a43e1aeacc804ecfc745b6223447538ab9355734 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Manager.php @@ -0,0 +1,331 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +use ArrayObject; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Config\CacheInterface; +use Magento\Framework\View\Element\UiComponent\ArrayObjectFactory; +use Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollectorFactory; +use Magento\Framework\View\Element\UiComponent\Config\Provider\Component\Definition as ComponentDefinition; + +/** + * Class Manager + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Manager implements ManagerInterface +{ + /** + * ID in the storage cache + */ + const CACHE_ID = 'ui_component_configuration_data'; + + /** + * Configuration provider for UI component + * + * @var ComponentDefinition + */ + protected $componentConfigProvider; + + /** + * DOM document merger + * + * @var DomMergerInterface + */ + protected $domMerger; + + /** + * Factory for UI config reader + * + * @var ReaderFactory + */ + protected $readerFactory; + + /** + * Component data + * + * @var ArrayObject + */ + protected $componentsData; + + /** + * Components pool + * + * @var ArrayObject + */ + protected $componentsPool; + + /** + * Factory for ArrayObject + * + * @var ArrayObjectFactory + */ + protected $arrayObjectFactory; + + /** + * @var AggregatedFileCollectorFactory + */ + protected $aggregatedFileCollectorFactory; + + /** + * @var CacheInterface + */ + protected $cache; + + /** + * @var UiReaderInterface[] + */ + protected $uiReader; + + /** + * Constructor + * + * @param ComponentDefinition $componentConfigProvider + * @param DomMergerInterface $domMerger + * @param ReaderFactory $readerFactory + * @param ArrayObjectFactory $arrayObjectFactory + * @param AggregatedFileCollectorFactory $aggregatedFileCollectorFactory + * @param CacheInterface $cache + */ + public function __construct( + ComponentDefinition $componentConfigProvider, + DomMergerInterface $domMerger, + ReaderFactory $readerFactory, + ArrayObjectFactory $arrayObjectFactory, + AggregatedFileCollectorFactory $aggregatedFileCollectorFactory, + CacheInterface $cache + ) { + $this->componentConfigProvider = $componentConfigProvider; + $this->domMerger = $domMerger; + $this->readerFactory = $readerFactory; + $this->arrayObjectFactory = $arrayObjectFactory; + $this->componentsData = $this->arrayObjectFactory->create(); + $this->aggregatedFileCollectorFactory = $aggregatedFileCollectorFactory; + $this->cache = $cache; + } + + /** + * Get component data + * + * @param string $name + * @return array + */ + public function getData($name) + { + return (array) $this->componentsData->offsetGet($name); + } + + /** + * Has component data + * + * @param string $name + * @return bool + */ + protected function hasData($name) + { + return $this->componentsData->offsetExists($name); + } + + /** + * Prepare the initialization data of UI components + * + * @param string $name + * @return ManagerInterface + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function prepareData($name) + { + if ($name === null || $this->hasData($name)) { + throw new LocalizedException( + new \Magento\Framework\Phrase( + 'Initialization error component, check the ' + . 'spelling of the name or the correctness of the call.' + ) + ); + } + $this->componentsPool = $this->arrayObjectFactory->create(); + + $cacheID = static::CACHE_ID . '_' . $name; + $cachedPool = $this->cache->load($cacheID); + if ($cachedPool === false) { + $this->prepare($name); + $this->cache->save($this->componentsPool->serialize(), $cacheID); + } else { + $this->componentsPool->unserialize($cachedPool); + } + $this->componentsData->offsetSet($name, $this->componentsPool); + + return $this; + } + + /** + * To create the raw data components + * + * @param string $component + * @return array + */ + public function createRawComponentData($component) + { + $componentData = $this->componentConfigProvider->getComponentData($component); + $componentData[Converter::DATA_ATTRIBUTES_KEY] = isset($componentData[Converter::DATA_ATTRIBUTES_KEY]) + ? $componentData[Converter::DATA_ATTRIBUTES_KEY] + : []; + $componentData[Converter::DATA_ARGUMENTS_KEY] = isset($componentData[Converter::DATA_ARGUMENTS_KEY]) + ? $componentData[Converter::DATA_ARGUMENTS_KEY] + : []; + + return [ + ManagerInterface::COMPONENT_ATTRIBUTES_KEY => $componentData[Converter::DATA_ATTRIBUTES_KEY], + ManagerInterface::COMPONENT_ARGUMENTS_KEY => $componentData[Converter::DATA_ARGUMENTS_KEY], + ]; + } + + /** + * Get UIReader and collect base files configuration + * + * @param string $name + * @return UiReaderInterface + */ + public function getReader($name) + { + if (!isset($this->uiReader[$name])) { + $this->domMerger->unsetDom(); + $this->uiReader[$name] = $this->readerFactory->create( + [ + 'fileCollector' => $this->aggregatedFileCollectorFactory->create( + ['searchPattern' => sprintf(ManagerInterface::SEARCH_PATTERN, $name)] + ), + 'domMerger' => $this->domMerger + ] + ); + } + + return $this->uiReader[$name]; + } + + /** + * Initialize the new component data + * + * @param string $name + * @return void + */ + protected function prepare($name) + { + $componentData = $this->getReader($name)->read(); + $componentsPool = reset($componentData); + $componentsPool = reset($componentsPool); + $componentsPool[Converter::DATA_ATTRIBUTES_KEY] = array_merge( + ['name' => $name], + $componentsPool[Converter::DATA_ATTRIBUTES_KEY] + ); + $components = $this->createDataForComponent(key($componentData), [$componentsPool]); + $this->addComponentIntoPool($name, reset($components)); + } + + /** + * Create data for component instance + * + * @param string $name + * @param array $componentsPool + * @return array + */ + protected function createDataForComponent($name, array $componentsPool) + { + $createdComponents = []; + $rootComponent = $this->createRawComponentData($name); + foreach ($componentsPool as $key => $component) { + $resultConfiguration = [ManagerInterface::CHILDREN_KEY => []]; + $instanceName = $this->createName($component, $key, $name); + $resultConfiguration[ManagerInterface::COMPONENT_ARGUMENTS_KEY] = $this->mergeArguments( + $component, + $rootComponent + ); + unset($component[Converter::DATA_ARGUMENTS_KEY]); + $resultConfiguration[ManagerInterface::COMPONENT_ATTRIBUTES_KEY] = $this->mergeAttributes( + $component, + $rootComponent + ); + unset($component[Converter::DATA_ATTRIBUTES_KEY]); + // Create inner components + foreach ($component as $subComponentName => $subComponent) { + $resultConfiguration[ManagerInterface::CHILDREN_KEY] = array_merge( + $resultConfiguration[ManagerInterface::CHILDREN_KEY], + $this->createDataForComponent($subComponentName, $subComponent) + ); + } + $createdComponents[$instanceName] = $resultConfiguration; + } + + return $createdComponents; + } + + /** + * Add a component into pool + * + * @param string $instanceName + * @param array $configuration + * @return void + */ + protected function addComponentIntoPool($instanceName, array $configuration) + { + $this->componentsPool->offsetSet($instanceName, $configuration); + } + + /** + * Merge component arguments + * + * @param array $componentData + * @param array $rootComponentData + * @return array + */ + protected function mergeArguments(array $componentData, array $rootComponentData) + { + $baseArguments = isset($rootComponentData[ManagerInterface::COMPONENT_ARGUMENTS_KEY]) + ? $rootComponentData[ManagerInterface::COMPONENT_ARGUMENTS_KEY] + : []; + $componentArguments = isset($componentData[Converter::DATA_ARGUMENTS_KEY]) + ? $componentData[Converter::DATA_ARGUMENTS_KEY] + : []; + + return array_replace_recursive($baseArguments, $componentArguments); + } + + /** + * Merge component attributes + * + * @param array $componentData + * @param array $rootComponentData + * @return array + */ + protected function mergeAttributes(array $componentData, array $rootComponentData) + { + $baseAttributes = isset($rootComponentData[ManagerInterface::COMPONENT_ATTRIBUTES_KEY]) + ? $rootComponentData[ManagerInterface::COMPONENT_ATTRIBUTES_KEY] + : []; + $componentAttributes = isset($componentData[Converter::DATA_ATTRIBUTES_KEY]) + ? $componentData[Converter::DATA_ATTRIBUTES_KEY] + : []; + unset($componentAttributes['noNamespaceSchemaLocation']); + + return array_replace_recursive($baseAttributes, $componentAttributes); + } + + /** + * Create name component instance + * + * @param array $componentData + * @param string|int $key + * @param string $componentName + * @return string + */ + protected function createName(array $componentData, $key, $componentName) + { + return isset($componentData[Converter::DATA_ATTRIBUTES_KEY][Converter::NAME_ATTRIBUTE_KEY]) + ? $componentData[Converter::DATA_ATTRIBUTES_KEY][Converter::NAME_ATTRIBUTE_KEY] + : sprintf(ManagerInterface::ANONYMOUS_TEMPLATE, $componentName, $key); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..29f26032ad8ffc7e5efafc5274718aaa49480a21 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +use Magento\Framework\Exception\LocalizedException; + +/** + * Interface ManagerInterface + */ +interface ManagerInterface +{ + /** + * Search pattern + */ + const SEARCH_PATTERN = '%s.xml'; + + /** + * The anonymous template name + */ + const ANONYMOUS_TEMPLATE = 'anonymous_%s_component_%d'; + + /** + * The key arguments in the data component + */ + const COMPONENT_ARGUMENTS_KEY = 'arguments'; + + /** + * The key attributes in the data component + */ + const COMPONENT_ATTRIBUTES_KEY = 'attributes'; + + /** + * The array key sub components + */ + const CHILDREN_KEY = 'children'; + + /** + * Prepare the initialization data of UI components + * + * @param string $name + * @return ManagerInterface + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function prepareData($name); + + /** + * Get component data + * + * @param string $name + * @return array + */ + public function getData($name); + + /** + * To create the raw data components + * + * @param string $component + * @return array + */ + public function createRawComponentData($component); + + /** + * Get UIReader and collect base files configuration + * + * @param string $name + * @return UiReaderInterface + */ + public function getReader($name); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php new file mode 100644 index 0000000000000000000000000000000000000000..7e7e27bed013d0205c3f2f00c2112b9ba635b39e --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config\Provider\Component; + +use Magento\Framework\Config\CacheInterface; +use Magento\Framework\View\Element\UiComponent\Config\Converter; +use Magento\Framework\View\Element\UiComponent\ArrayObjectFactory; +use Magento\Framework\View\Element\UiComponent\Config\UiReaderInterface; + +/** + * Class Definition + */ +class Definition +{ + /** + * ID in the storage cache + */ + const CACHE_ID = 'ui_component_definition_data'; + + /** + * Components node name in config + */ + const COMPONENTS_KEY = 'components'; + + /** + * @var CacheInterface + */ + protected $cache; + + /** + * UI component data + * + * @var \ArrayObject + */ + protected $componentData; + + /** + * Constructor + * + * @param UiReaderInterface $uiReader + * @param ArrayObjectFactory $arrayObjectFactory + * @param CacheInterface $cache + */ + public function __construct( + UiReaderInterface $uiReader, + ArrayObjectFactory $arrayObjectFactory, + CacheInterface $cache + ) { + $this->cache = $cache; + $this->componentData = $arrayObjectFactory->create(); + $cachedData = $this->cache->load(static::CACHE_ID); + if ($cachedData === false) { + $data = $uiReader->read(); + $this->cache->save(serialize($data), static::CACHE_ID); + } else { + $data = unserialize($cachedData); + } + $this->prepareComponentData($data); + } + + /** + * Get component data + * + * @param string $name + * @return array + */ + public function getComponentData($name) + { + return (array) $this->componentData->offsetGet($name); + } + + /** + * Set component data + * + * @param string $name + * @param array $data + * @return void + */ + public function setComponentData($name, array $data) + { + $this->componentData->offsetSet($name, $data); + } + + /** + * Prepare configuration data for the component + * + * @param array $componentsData + * @return void + */ + protected function prepareComponentData(array $componentsData) + { + $componentsData = reset($componentsData[static::COMPONENTS_KEY]); + unset($componentsData[Converter::DATA_ATTRIBUTES_KEY]); + foreach ($componentsData as $name => $data) { + $this->setComponentData($name, reset($data)); + } + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php new file mode 100644 index 0000000000000000000000000000000000000000..1c47f39a1a993e2b80a9e4d0d67fe5e1858dfe6d --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php @@ -0,0 +1,111 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config\Provider; + +use Magento\Framework\Config\CacheInterface; +use Magento\Framework\View\Element\UiComponent\Config\ReaderFactory; +use Magento\Framework\View\Element\UiComponent\Config\DomMergerInterface; +use Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollector; +use Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollectorFactory; + +/** + * Class Template + */ +class Template +{ + /** + * Components node name in config + */ + const TEMPLATE_KEY = 'template'; + + /** + * ID in the storage cache + */ + const CACHE_ID = 'ui_component_templates'; + + /** + * @var AggregatedFileCollector + */ + protected $aggregatedFileCollector; + + /** + * @var DomMergerInterface + */ + protected $domMerger; + + /** + * @var CacheInterface + */ + protected $cache; + + /** + * Factory for UI config reader + * + * @var ReaderFactory + */ + protected $readerFactory; + + /** + * @var AggregatedFileCollectorFactory + */ + protected $aggregatedFileCollectorFactory; + + /** + * @var array + */ + protected $cachedTemplates = []; + + /** + * Constructor + * + * @param AggregatedFileCollector $aggregatedFileCollector + * @param DomMergerInterface $domMerger + * @param CacheInterface $cache + * @param ReaderFactory $readerFactory + * @param AggregatedFileCollectorFactory $aggregatedFileCollectorFactory + */ + public function __construct( + AggregatedFileCollector $aggregatedFileCollector, + DomMergerInterface $domMerger, + CacheInterface $cache, + ReaderFactory $readerFactory, + AggregatedFileCollectorFactory $aggregatedFileCollectorFactory + ) { + $this->aggregatedFileCollector = $aggregatedFileCollector; + $this->domMerger = $domMerger; + $this->cache = $cache; + $this->readerFactory = $readerFactory; + $this->aggregatedFileCollectorFactory = $aggregatedFileCollectorFactory; + + $cachedTemplates = $this->cache->load(static::CACHE_ID); + $this->cachedTemplates = $cachedTemplates === false ? [] : unserialize($cachedTemplates); + } + + /** + * Get template content + * + * @param string $template + * @return string + * @throws \Exception + */ + public function getTemplate($template) + { + $hash = sprintf('%x', crc32($template)); + if (isset($this->cachedTemplates[$hash])) { + return $this->cachedTemplates[$hash]; + } + + $this->cachedTemplates[$hash] = $this->readerFactory->create( + [ + 'fileCollector' => $this->aggregatedFileCollectorFactory->create(['searchPattern' => $template]), + 'domMerger' => $this->domMerger + ] + )->getContent(); + $this->cache->save(serialize($this->cachedTemplates), static::CACHE_ID); + + return $this->cachedTemplates[$hash]; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Reader.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Reader.php new file mode 100644 index 0000000000000000000000000000000000000000..13ddec6465bf1995527ec36381856640f08531fd --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Reader.php @@ -0,0 +1,117 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +use Magento\Framework\Filesystem; +use Magento\Framework\Config\ConverterInterface; +use Magento\Framework\Config\FileIteratorFactory; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem\Directory\ReadInterface; + +/** + * Class Reader + */ +class Reader implements UiReaderInterface +{ + /** + * DOM document merger + * + * @var DomMergerInterface + */ + protected $domMerger; + + /** + * XML converter + * + * @var ConverterInterface + */ + protected $converter; + + /** + * Constructor + * + * @param FileCollectorInterface $fileCollector + * @param ConverterInterface $converter + * @param DomMergerInterface $domMerger + */ + public function __construct( + FileCollectorInterface $fileCollector, + ConverterInterface $converter, + DomMergerInterface $domMerger + ) { + $this->converter = $converter; + $this->domMerger = $domMerger; + $this->readFiles($fileCollector->collectFiles()); + } + + /** + * Read configuration files + * + * @param array $fileList + * @return array + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function readFiles(array $fileList) + { + foreach ($fileList as $fileContent) { + $this->domMerger->merge($fileContent); + } + } + + /** + * Add xml content in the merged file + * + * @param string $xmlContent + * @return void + */ + public function addXMLContent($xmlContent) + { + $this->domMerger->merge($xmlContent); + } + + /** + * Add DOM node into DOM document + * + * @param \DOMNode $node + * @return void + */ + public function addNode(\DOMNode $node) + { + $this->domMerger->mergeNode($node); + } + + /** + * Load configuration scope + * + * @param string|null $scope + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function read($scope = null) + { + return $this->converter->convert($this->domMerger->getDom()); + } + + /** + * Get content from the merged files + * + * @return string + */ + public function getContent() + { + return $this->domMerger->getDom()->saveXML(); + } + + /** + * Get DOM document + * + * @return \DOMDocument + */ + public function getDOMDocument() + { + return $this->domMerger->getDom(); + } +} diff --git a/app/code/Magento/Ui/DataProvider/Factory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ReaderFactory.php similarity index 61% rename from app/code/Magento/Ui/DataProvider/Factory.php rename to lib/internal/Magento/Framework/View/Element/UiComponent/Config/ReaderFactory.php index c24c9d58bee80128958c3062dd41070624f131e9..3efb30cb1141dd4e0621fa1c614caf7665f79a51 100644 --- a/app/code/Magento/Ui/DataProvider/Factory.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ReaderFactory.php @@ -3,15 +3,17 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\DataProvider; +namespace Magento\Framework\View\Element\UiComponent\Config; use Magento\Framework\ObjectManagerInterface; /** - * Class Factory + * Class ReaderFactory */ -class Factory +class ReaderFactory { + const INSTANCE_NAME = 'Magento\Framework\View\Element\UiComponent\Config\Reader'; + /** * @var ObjectManagerInterface */ @@ -28,14 +30,13 @@ class Factory } /** - * Create data provider + * Create config reader * - * @param string $providerClass * @param array $arguments - * @return mixed + * @return UiReaderInterface */ - public function create($providerClass, array $arguments = []) + public function create(array $arguments = []) { - return $this->objectManager->create($providerClass, ['arguments' => $arguments]); + return $this->objectManager->create(static::INSTANCE_NAME, $arguments); } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/UiReaderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/UiReaderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a9c1915131fab999a939b2bf294eaa745926f15a --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/UiReaderInterface.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Config; + +use Magento\Framework\Config\ReaderInterface; + +/** + * Interface UiReaderInterface + */ +interface UiReaderInterface extends ReaderInterface +{ + /** + * Add xml content in the merged file + * + * @param string $xmlContent + * @return void + */ + public function addXMLContent($xmlContent); + + /** + * Get content from the merged files + * + * @return string + */ + public function getContent(); + + /** + * Get DOM document + * + * @return \DOMDocument + */ + public function getDOMDocument(); + + /** + * Add DOM node into DOM document + * + * @param \DOMNode $node + * @return void + */ + public function addNode(\DOMNode $node); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigBuilderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigBuilderInterface.php deleted file mode 100644 index bba2e86556c49b6eb924e99c2a1e6bec70109dcf..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigBuilderInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\View\Element\UiComponent; - -/** - * Interface ConfigBuilderInterface - */ -interface ConfigBuilderInterface -{ - /** - * Config data to JSON by output - * - * @param ConfigInterface $configuration - * @return string - */ - public function toJson(ConfigInterface $configuration); -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigFactory.php deleted file mode 100644 index 9470ec3119f2bba2b1956c0a82d32dbda6d443bb..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigFactory.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\View\Element\UiComponent; - -use Magento\Framework\ObjectManagerInterface; - -/** - * Class ConfigFactory - */ -class ConfigFactory -{ - /** - * Object Manager instance - * - * @var ObjectManagerInterface - */ - protected $objectManager = null; - - /** - * Instance name to create - * - * @var string - */ - protected $instanceName = null; - - /** - * Factory constructor - * - * @param ObjectManagerInterface $objectManager - * @param string $instanceName - */ - public function __construct( - ObjectManagerInterface $objectManager, - $instanceName = 'Magento\Framework\View\Element\UiComponent\ConfigInterface' - ) { - $this->objectManager = $objectManager; - $this->instanceName = $instanceName; - } - - /** - * Create class instance with specified parameters - * - * @param array $data - * @return \Magento\Framework\View\Element\UiComponent\ConfigInterface - */ - public function create(array $data = []) - { - return $this->objectManager->create($this->instanceName, $data); - } -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigInterface.php deleted file mode 100644 index ad665bc3de14e7b1d5470a65f13f498b07b93c83..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\View\Element\UiComponent; - -/** - * Class ConfigInterface - */ -interface ConfigInterface -{ - /** - * Get configuration data - * - * @param string|null $key - * @return mixed - */ - public function getData($key = null); - - /** - * Add configuration data - * - * @param string $key - * @param mixed $data - * @return mixed - */ - public function addData($key, $data); - - /** - * Update configuration data - * - * @param string $key - * @param mixed $data - * @return mixed - */ - public function updateData($key, $data); - - /** - * Get owner name - * - * @return string - */ - public function getName(); - - /** - * Get owner parent name - * - * @return string - */ - public function getParentName(); -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageBuilderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageBuilderInterface.php deleted file mode 100644 index ef081fd327d6f7a2a82f2f520cf6996e615426fe..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageBuilderInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\View\Element\UiComponent; - -/** - * Interface ConfigStorageBuilderInterface - */ -interface ConfigStorageBuilderInterface -{ - /** - * Config storage data to JSON by output - * - * @param ConfigStorageInterface $storage - * @param string $parentName - * @return string - */ - public function toJson(ConfigStorageInterface $storage, $parentName = null); -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageInterface.php deleted file mode 100644 index 3b31ff3e7de77de41d104050c5b929dbc818669e..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageInterface.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\View\Element\UiComponent; - -use Magento\Framework\Api\CriteriaInterface; -use Magento\Framework\Data\CollectionDataSourceInterface; - -/** - * Class ConfigurationStorageInterface - */ -interface ConfigStorageInterface -{ - /** - * Register component - * - * @param string $name - * @param array $data - * @return mixed - */ - public function addComponent($name, $data); - - /** - * Add components configuration - * - * @param ConfigInterface $config - * @return void - */ - public function addComponentsData(ConfigInterface $config); - - /** - * Remove components configuration - * - * @param ConfigInterface $configuration - * @return void - */ - public function removeComponentsData(ConfigInterface $configuration); - - /** - * Get components configuration - * - * @param string|null $name - * @return ConfigInterface|null|array - */ - public function getComponentsData($name = null); - - /** - * @return array - */ - public function getComponents(); - - /** - * Add data in storage - * - * @param string $name - * @param array $dataSource - * @return void - */ - public function addDataSource($name, array $dataSource); - - /** - * Remove data in storage - * - * @param string $name - * @return void - */ - public function removeDataSource($name); - - /** - * Get data from storage - * - * @param string|null $name - * @return array|null - */ - public function getDataSource($name = null); - - /** - * Update data in storage - * - * @param string $name - * @param array $dataSource - * @return void - */ - public function updateDataSource($name, array $dataSource); - - /** - * Add meta data - * - * @param string $key - * @param array $data - * @return mixed - */ - public function addMeta($key, array $data); - - /** - * Remove meta data - * - * @param string $key - * @return array - */ - public function removeMeta($key); - - /** - * Get meta data - * - * @param string|null $key - * @return array|null - */ - public function getMeta($key = null); - - /** - * Update meta data in storage - * - * @param string $key - * @param array $data - * @return void - */ - public function updateMeta($key, array $data); - - /** - * @return array - */ - public function getMetaKeys(); - - /** - * Set data collection - * - * @param string $key - * @param CollectionDataSourceInterface|CriteriaInterface $dataCollection - * @return void - */ - public function addDataCollection($key, CollectionDataSourceInterface $dataCollection); - - /** - * Get data collection - * - * @param string|null $key - * @return CollectionDataSourceInterface|CriteriaInterface - */ - public function getDataCollection($key = null); - - /** - * Update data collection in storage - * - * @param string $key - * @param CollectionDataSourceInterface|CriteriaInterface $dataCollection - * @return mixed - */ - public function updateDataCollection($key, CollectionDataSourceInterface $dataCollection); - - /** - * Add cloud data in storage - * - * @param string $key - * @param array $data - * @return void - */ - public function addGlobalData($key, array $data); - - /** - * Remove cloud data in storage - * - * @param string $key - * @return void - */ - public function removeGlobalData($key); - - /** - * Get cloud data from storage - * - * @param string|null $key - * @return array|null - */ - public function getGlobalData($key = null); - - /** - * @param string $key - * @param DataProviderInterface $dataProvider - * @return void - */ - public function addDataProvider($key, DataProviderInterface $dataProvider); - - /** - * @param string $key - * @return void - */ - public function removeDataProvider($key); - - /** - * @param null|string $key - * @return DataProviderInterface[]|DataProviderInterface|null - */ - public function getDataProvider($key = null); - - /** - * @param string $key - * @param DataProviderInterface $dataProvider - * @return void - */ - public function updateDataProvider($key, DataProviderInterface $dataProvider); - - /** - * @param string $dataScope - * @param array $structure - * @return void - */ - public function addLayoutStructure($dataScope, array $structure); - - /** - * @return array - */ - public function getLayoutStructure(); - - /** - * @param string $name - * @param mixed $default - * @return array - */ - public function getLayoutNode($name, $default = null); -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContainerInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContainerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..4966134eaf77811bc53bf5d1cd6bb5cafdba74a7 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContainerInterface.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent; + +use Magento\Framework\View\Element\BlockInterface; + +/** + * Interface ContainerInterface + */ +interface ContainerInterface extends BlockInterface +{ + // +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/AbstractContentType.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/AbstractContentType.php new file mode 100644 index 0000000000000000000000000000000000000000..72c021138f7892e7ae8e24d71f00ac7252fe3a14 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/AbstractContentType.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\ContentType; + +use Magento\Framework\View\FileSystem; +use Magento\Framework\View\TemplateEnginePool; + +/** + * Class AbstractContentType + */ +abstract class AbstractContentType implements ContentTypeInterface +{ + /** + * @var FileSystem + */ + protected $filesystem; + + /** + * @var TemplateEnginePool + */ + protected $templateEnginePool; + + /** + * Constructor + * + * @param FileSystem $filesystem + * @param TemplateEnginePool $templateEnginePool + */ + public function __construct( + FileSystem $filesystem, + TemplateEnginePool $templateEnginePool + ) { + $this->filesystem = $filesystem; + $this->templateEnginePool = $templateEnginePool; + } +} diff --git a/app/code/Magento/Ui/ContentType/ContentTypeFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeFactory.php similarity index 72% rename from app/code/Magento/Ui/ContentType/ContentTypeFactory.php rename to lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeFactory.php index 5bdda92584f66a60744b4e22b654b89110086a0d..886331cf65935b7662688e42fcf22c5c009cf162 100644 --- a/app/code/Magento/Ui/ContentType/ContentTypeFactory.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeFactory.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\ContentType; +namespace Magento\Framework\View\Element\UiComponent\ContentType; use Magento\Framework\ObjectManagerInterface; @@ -12,26 +12,17 @@ use Magento\Framework\ObjectManagerInterface; */ class ContentTypeFactory { - /** - * Default content type - */ - const DEFAULT_TYPE = 'html'; - /** * Content types * * @var array */ - protected $types = [ - 'html' => 'Magento\Ui\ContentType\Html', - 'json' => 'Magento\Ui\ContentType\Json', - 'xml' => 'Magento\Ui\ContentType\Xml', - ]; + protected $types; /** * Object manager * - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ protected $objectManager; @@ -41,9 +32,9 @@ class ContentTypeFactory * @param ObjectManagerInterface $objectManager * @param array $types */ - public function __construct(ObjectManagerInterface $objectManager, array $types = []) + public function __construct(ObjectManagerInterface $objectManager, array $types) { - $this->types = array_merge($this->types, $types); + $this->types = $types; $this->objectManager = $objectManager; } @@ -54,7 +45,7 @@ class ContentTypeFactory * @return ContentTypeInterface * @throws \InvalidArgumentException */ - public function get($type = ContentTypeFactory::DEFAULT_TYPE) + public function get($type) { if (!isset($this->types[$type])) { throw new \InvalidArgumentException(sprintf("Wrong content type '%s', renderer not exists.", $type)); diff --git a/app/code/Magento/Ui/ContentType/ContentTypeInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeInterface.php similarity index 55% rename from app/code/Magento/Ui/ContentType/ContentTypeInterface.php rename to lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeInterface.php index 575c42e77d1dd9f0b6108be376c61654e9ce6656..cbefd547d9caae922abf02085c51feeb603d29f8 100644 --- a/app/code/Magento/Ui/ContentType/ContentTypeInterface.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeInterface.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\ContentType; +namespace Magento\Framework\View\Element\UiComponent\ContentType; use Magento\Framework\View\Element\UiComponentInterface; @@ -13,11 +13,11 @@ use Magento\Framework\View\Element\UiComponentInterface; interface ContentTypeInterface { /** - * Render data + * Render component * - * @param UiComponentInterface $view + * @param UiComponentInterface $component * @param string $template - * @return mixed + * @return string */ - public function render(UiComponentInterface $view, $template = ''); + public function render(UiComponentInterface $component, $template = ''); } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Html.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Html.php new file mode 100644 index 0000000000000000000000000000000000000000..4283327e3e86bd5ecd8eb6486d66a8c2489da20c --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Html.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\ContentType; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Html + */ +class Html extends AbstractContentType +{ + /** + * Render data + * + * @param UiComponentInterface $component + * @param string $template + * @return string + */ + public function render(UiComponentInterface $component, $template = '') + { + $result = ''; + if ($template) { + $extension = pathinfo($template, PATHINFO_EXTENSION); + $templateEngine = $this->templateEnginePool->get($extension); + $result = $templateEngine->render($component, $this->getTemplate($extension, $template)); + } + return $result; + } + + /** + * Get template path + * + * @param string $extension + * @param string $template + * @return string + */ + protected function getTemplate($extension, $template) + { + switch ($extension) { + case 'xhtml': + return $template; + default: + return $this->filesystem->getTemplateFileName($template); + } + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Json.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Json.php new file mode 100644 index 0000000000000000000000000000000000000000..3185bc6cb2ac0b83581502f57e48607b624257ab --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Json.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\ContentType; + +use Magento\Framework\View\FileSystem; +use Magento\Framework\View\TemplateEnginePool; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Class Json + */ +class Json extends AbstractContentType +{ + /** + * Constructor + * + * @param FileSystem $filesystem + * @param TemplateEnginePool $templateEnginePool + */ + public function __construct( + FileSystem $filesystem, + TemplateEnginePool $templateEnginePool + ) { + parent::__construct($filesystem, $templateEnginePool); + } + + /** + * Render data + * + * @param UiComponentInterface $component + * @param string $template + * @return string + * @throws \Exception + */ + public function render(UiComponentInterface $component, $template = '') + { + $data = $component->getDataSourceData(); + $data = reset($data); + + return json_encode($data['config']['data']); + } +} diff --git a/app/code/Magento/Ui/ContentType/Xml.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Xml.php similarity index 82% rename from app/code/Magento/Ui/ContentType/Xml.php rename to lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Xml.php index 065a34d73a17f71633cc5ee3ea702bd1e4d77915..9715e8d6ea510e4861d6e5cc3ed4535baa303e9e 100644 --- a/app/code/Magento/Ui/ContentType/Xml.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Xml.php @@ -3,43 +3,47 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\ContentType; +namespace Magento\Framework\View\Element\UiComponent\ContentType; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Xml\Generator; use Magento\Framework\View\FileSystem; use Magento\Framework\View\TemplateEnginePool; -use Magento\Framework\Xml\Generator; +use Magento\Framework\View\Element\UiComponentInterface; /** * Class Xml */ -class Xml implements ContentTypeInterface +class Xml extends AbstractContentType { /** - * @var \Magento\Framework\View\FileSystem + * @var FileSystem */ protected $filesystem; /** - * @var \Magento\Framework\View\TemplateEnginePool + * @var TemplateEnginePool */ protected $templateEnginePool; /** - * @var \Magento\Framework\Xml\Generator + * @var Generator */ protected $generator; /** + * Constructor + * * @param FileSystem $filesystem * @param TemplateEnginePool $templateEnginePool * @param Generator $generator */ - public function __construct(FileSystem $filesystem, TemplateEnginePool $templateEnginePool, Generator $generator) - { - $this->filesystem = $filesystem; - $this->templateEnginePool = $templateEnginePool; + public function __construct( + FileSystem $filesystem, + TemplateEnginePool $templateEnginePool, + Generator $generator + ) { $this->generator = $generator; + parent::__construct($filesystem, $templateEnginePool); } /** @@ -48,6 +52,7 @@ class Xml implements ContentTypeInterface * @param UiComponentInterface $view * @param string $template * @return string + * @throws \Exception */ public function render(UiComponentInterface $view, $template = '') { @@ -62,7 +67,8 @@ class Xml implements ContentTypeInterface } else { $result = $this->getDataXml($view); } - return $result; + + throw new \Exception('Please implement XML renderer'); } /** diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php index 582fad08370f42cba9aac5880f3fd353e8adfc78..2e9e35bce7ef1db4cc563e3d15d3ffed00f6f85e 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php @@ -5,29 +5,32 @@ */ namespace Magento\Framework\View\Element\UiComponent; +use Magento\Framework\UrlInterface; use Magento\Framework\App\RequestInterface; -use Magento\Framework\Registry; -use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Framework\View\LayoutInterface; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\Control\ActionPoolFactory; +use Magento\Framework\View\Element\UiComponent\Control\ActionPoolInterface; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderFactory; +use Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeFactory; +use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; +use Magento\Framework\View\LayoutInterface as PageLayoutInterface; /** * Class Context */ -class Context extends Registry +class Context implements ContextInterface { /** - * Configuration storage builder - * - * @var ConfigStorageBuilderInterface + * @var string */ - protected $configStorageBuilder; + protected $namespace; /** - * Configuration storage - * - * @var ConfigStorageInterface + * @var DataProviderInterface */ - protected $configStorage; + protected $dataProvider; /** * Application request @@ -36,6 +39,13 @@ class Context extends Registry */ protected $request; + /** + * Factory renderer for a content type + * + * @var ContentTypeFactory + */ + protected $contentTypeFactory; + /** * Accept type * @@ -44,191 +54,249 @@ class Context extends Registry protected $acceptType; /** - * @var LayoutInterface + * @var PageLayoutInterface */ protected $pageLayout; /** - * @var LayoutInterface + * @var ButtonProviderFactory */ - protected $layout; + protected $buttonProviderFactory; /** - * @var UiComponentFactory + * @var ActionPoolInterface */ - protected $factory; + protected $actionPool; /** - * Data Namespace + * Registry components * - * @var string + * @var array */ - protected $namespace; + protected $componentsDefinitions = []; /** - * Constructor + * Url Builder * - * @param ConfigStorageInterface $configStorage - * @param ConfigStorageBuilderInterface $configStorageBuilder + * @var UrlInterface + */ + protected $urlBuilder; + + /** + * @param PageLayoutInterface $pageLayout * @param RequestInterface $request + * @param ButtonProviderFactory $buttonProviderFactory + * @param ActionPoolFactory $actionPoolFactory + * @param ContentTypeFactory $contentTypeFactory + * @param UrlInterface $urlBuilder + * @param DataProviderInterface|null $dataProvider + * @param string $namespace */ public function __construct( - ConfigStorageInterface $configStorage, - ConfigStorageBuilderInterface $configStorageBuilder, - RequestInterface $request + PageLayoutInterface $pageLayout, + RequestInterface $request, + ButtonProviderFactory $buttonProviderFactory, + ActionPoolFactory $actionPoolFactory, + ContentTypeFactory $contentTypeFactory, + UrlInterface $urlBuilder, + DataProviderInterface $dataProvider = null, + $namespace = null ) { - $this->configStorage = $configStorage; - $this->configStorageBuilder = $configStorageBuilder; + $this->namespace = $namespace; $this->request = $request; + $this->buttonProviderFactory = $buttonProviderFactory; + $this->dataProvider = $dataProvider; + $this->pageLayout = $pageLayout; + $this->actionPool = $actionPoolFactory->create(['context' => $this]); + $this->contentTypeFactory = $contentTypeFactory; + $this->urlBuilder = $urlBuilder; + $this->setAcceptType(); } /** - * Getting requested accept type + * Add component into registry * + * @param string $name + * @param array $config * @return void */ - protected function setAcceptType() + public function addComponentDefinition($name, array $config) { - $this->acceptType = 'xml'; - - $rawAcceptType = $this->request->getHeader('Accept'); - if (strpos($rawAcceptType, 'json') !== false) { - $this->acceptType = 'json'; - } elseif (strpos($rawAcceptType, 'html') !== false) { - $this->acceptType = 'html'; + if (!isset($this->componentsDefinitions[$name])) { + $this->componentsDefinitions[$name] = $config; } } /** - * Getting accept type + * To get the registry components * - * @return string + * @return array */ - public function getAcceptType() + public function getComponentsDefinitions() { - return $this->acceptType; + return $this->componentsDefinitions; } /** - * Set Ui Components Factory + * Get render engine * - * @param UiComponentFactory $render - * @return void + * @return ContentTypeInterface */ - public function setRender(UiComponentFactory $render) + public function getRenderEngine() { - $this->factory = $render; + return $this->contentTypeFactory->get($this->getAcceptType()); } /** - * Get Ui Components Factory - * - * @return UiComponentFactory + * @return string */ - public function getRender() + public function getNamespace() { - return $this->factory; + return $this->namespace; } /** - * Set root layout + * Getting accept type * - * @param LayoutInterface $layout - * @return void + * @return string */ - public function setPageLayout(LayoutInterface $layout) + public function getAcceptType() { - $this->pageLayout = $layout; + return $this->acceptType; } /** - * Get root layout + * Getting all request data * - * @return LayoutInterface + * @return mixed */ - public function getPageLayout() + public function getRequestParams() { - return $this->pageLayout; + return $this->request->getParams(); } /** - * Set root view + * Getting data according to the key * - * @param string $namespace - * @return void + * @param string $key + * @param mixed|null $defaultValue + * @return mixed */ - public function setNamespace($namespace) + public function getRequestParam($key, $defaultValue = null) { - $this->namespace = $namespace; + return $this->request->getParam($key, $defaultValue); } /** - * Get root view + * Get data provider * - * @return string + * @return DataProviderInterface */ - public function getNamespace() + public function getDataProvider() { - return $this->namespace; + return $this->dataProvider; } /** - * Getting all request data + * Get page layout * - * @return mixed + * @return PageLayoutInterface */ - public function getRequestParams() + public function getPageLayout() { - return $this->request->getParams(); + return $this->pageLayout; } /** - * Getting data according to the key + * Add button in the actions toolbar * - * @param string $key - * @param mixed|null $defaultValue - * @return mixed + * @param array $buttons + * @param UiComponentInterface $component + * @return void */ - public function getRequestParam($key, $defaultValue = null) + public function addButtons(array $buttons, UiComponentInterface $component) { - return $this->request->getParam($key, $defaultValue); + if (!empty($buttons)) { + foreach ($buttons as $buttonId => $buttonData) { + if (is_array($buttonData)) { + $buttons[$buttonId] = $buttonData; + continue; + } + /** @var ButtonProviderInterface $button */ + $button = $this->buttonProviderFactory->create($buttonData); + $buttonData = $button->getButtonData(); + if (!$buttonData) { + unset($buttons[$buttonId]); + continue; + } + $buttons[$buttonId] = $buttonData; + } + uasort($buttons, [$this, 'sortButtons']); + + foreach ($buttons as $buttonId => $buttonData) { + if (isset($buttonData['url'])) { + $buttonData['url'] = $this->getUrl($buttonData['url']); + } + $this->actionPool->add($buttonId, $buttonData, $component); + } + } } /** - * Get storage configuration + * Sort buttons by sort order * - * @return ConfigStorageInterface + * @param array $itemA + * @param array $itemB + * @return int */ - public function getStorage() + public function sortButtons(array $itemA, array $itemB) { - return $this->configStorage; + $sortOrderA = isset($itemA['sort_order']) ? intval($itemA['sort_order']) : 0; + $sortOrderB = isset($itemB['sort_order']) ? intval($itemB['sort_order']) : 0; + + return $sortOrderA - $sortOrderB; } /** - * Get configuration builder + * Getting requested accept type * - * @return ConfigStorageBuilderInterface + * @return void */ - public function getConfigBuilder() + protected function setAcceptType() { - return $this->configStorageBuilder; + $this->acceptType = 'html'; + + $rawAcceptType = $this->request->getHeader('Accept'); + if ($this->request->getParam('isAjax') === 'true' || strpos($rawAcceptType, 'json') !== false) { + $this->acceptType = 'json'; + } else if (strpos($rawAcceptType, 'html') !== false) { + $this->acceptType = 'html'; + } else if (strpos($rawAcceptType, 'xml') !== false) { + $this->acceptType = 'xml'; + } } /** - * @param LayoutInterface $layout + * Set data provider + * + * @param DataProviderInterface $dataProvider * @return void */ - public function setLayout(LayoutInterface $layout) + public function setDataProvider(DataProviderInterface $dataProvider) { - $this->layout = $layout; + $this->dataProvider = $dataProvider; } /** - * @return LayoutInterface + * Generate url by route and parameters + * + * @param string $route + * @param array $params + * @return string */ - public function getLayout() + public function getUrl($route = '', $params = []) { - return $this->layout; + return $this->urlBuilder->getUrl($route, $params); } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContextFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..5708da5d21278eb8342e92c4cd753e81e3158d40 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextFactory.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent; + +use Magento\Framework\ObjectManagerInterface; + +/** + * Class ContextFactory + */ +class ContextFactory +{ + const INSTANCE_NAME = 'Magento\Framework\View\Element\UiComponent\ContextInterface'; + + /** + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Create context + * + * @param array $arguments + * @return ContextInterface + */ + public function create(array $arguments = []) + { + return $this->objectManager->create(static::INSTANCE_NAME, $arguments); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContextInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..321f2cc5b2e066774a462c6a424edc4f43694384 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextInterface.php @@ -0,0 +1,110 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent; + +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; +use Magento\Framework\View\LayoutInterface as PageLayoutInterface; + +/** + * Interface ContextInterface + */ +interface ContextInterface +{ + /** + * Add components definition + * + * @param string $name + * @param array $config + * @return void + */ + public function addComponentDefinition($name, array $config); + + /** + * Get components definitions + * + * @return array + */ + public function getComponentsDefinitions(); + + /** + * Getting root component name + * + * @return string + */ + public function getNamespace(); + + /** + * Getting accept type + * + * @return string + */ + public function getAcceptType(); + + /** + * Set data provider + * + * @param DataProviderInterface $dataProvider + * @return void + */ + public function setDataProvider(DataProviderInterface $dataProvider); + + /** + * Get data provider + * + * @return DataProviderInterface + */ + public function getDataProvider(); + + /** + * Getting all request data + * + * @return mixed + */ + public function getRequestParams(); + + /** + * Getting data according to the key + * + * @param string $key + * @param mixed|null $defaultValue + * @return mixed + */ + public function getRequestParam($key, $defaultValue = null); + + /** + * Get root layout + * + * @return PageLayoutInterface + */ + public function getPageLayout(); + + /** + * Add button in the actions toolbar + * + * @param array $buttons + * @param UiComponentInterface $component + * @return void + */ + public function addButtons(array $buttons, UiComponentInterface $component); + + /** + * Get render engine + * + * @return ContentTypeInterface + */ + public function getRenderEngine(); + + /** + * Generate url by route and parameters + * + * @param string $route + * @param array $params + * @return string + */ + public function getUrl($route = '', $params = []); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ActionPoolFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ActionPoolFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..477ff99cebcb3ce5a129184330c43f4e47b4abc1 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ActionPoolFactory.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Control; + +use Magento\Framework\ObjectManagerInterface; + +/** + * Class ActionPoolFactory + */ +class ActionPoolFactory +{ + const INSTANCE = 'Magento\Framework\View\Element\UiComponent\Control\ActionPoolInterface'; + + /** + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Create Action Pool + * + * @param array $arguments + * @return ActionPoolInterface + */ + public function create(array $arguments = []) + { + return $this->objectManager->create(static::INSTANCE, $arguments); + } +} diff --git a/app/code/Magento/Ui/Component/Control/ActionPoolInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ActionPoolInterface.php similarity index 76% rename from app/code/Magento/Ui/Component/Control/ActionPoolInterface.php rename to lib/internal/Magento/Framework/View/Element/UiComponent/Control/ActionPoolInterface.php index 2a9d361a58f59c1c0ce9e7364eef0110c7e1a8b6..225bfe0dcf81b7faef0e797b4629bc7c0ec7a32e 100644 --- a/app/code/Magento/Ui/Component/Control/ActionPoolInterface.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ActionPoolInterface.php @@ -3,8 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\Component\Control; +namespace Magento\Framework\View\Element\UiComponent\Control; +use Magento\Framework\View\Element\BlockInterface; use Magento\Framework\View\Element\UiComponentInterface; /** @@ -38,4 +39,11 @@ interface ActionPoolInterface * @return void */ public function update($key, array $data); + + /** + * Get toolbar block + * + * @return bool|BlockInterface + */ + public function getToolbar(); } diff --git a/app/code/Magento/Ui/Component/Control/ButtonProviderFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ButtonProviderFactory.php similarity index 93% rename from app/code/Magento/Ui/Component/Control/ButtonProviderFactory.php rename to lib/internal/Magento/Framework/View/Element/UiComponent/Control/ButtonProviderFactory.php index c30c7a0f9ced52d49d42778a52063f4f27abca66..b4fe0c6561ebe8d033d2b58776b93819c4683e6f 100644 --- a/app/code/Magento/Ui/Component/Control/ButtonProviderFactory.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ButtonProviderFactory.php @@ -3,13 +3,12 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\Component\Control; +namespace Magento\Framework\View\Element\UiComponent\Control; use Magento\Framework\ObjectManagerInterface; /** * Class ButtonProviderFactory - * @package Magento\Ui\DataProvider */ class ButtonProviderFactory { @@ -43,6 +42,7 @@ class ButtonProviderFactory sprintf('"%s" must implement the interface ButtonProviderInterface.', $providerClass) ); } + return $object; } } diff --git a/app/code/Magento/Ui/Component/Control/ButtonProviderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ButtonProviderInterface.php similarity index 76% rename from app/code/Magento/Ui/Component/Control/ButtonProviderInterface.php rename to lib/internal/Magento/Framework/View/Element/UiComponent/Control/ButtonProviderInterface.php index 508ae595faac9f4b5929e04a5d6edbe16952e8bb..160968779bd5384033f1e617b3506ec99f1a5e09 100644 --- a/app/code/Magento/Ui/Component/Control/ButtonProviderInterface.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ButtonProviderInterface.php @@ -3,11 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\Component\Control; +namespace Magento\Framework\View\Element\UiComponent\Control; /** * Interface ButtonProviderInterface - * @package Magento\Ui\Component\Control */ interface ButtonProviderInterface { diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ControlInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ControlInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..2b5870a14a36e50048338dcac6dac21973c1c263 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Control/ControlInterface.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\Control; + +use Magento\Framework\View\Element\BlockInterface; + +/** + * Interface ControlInterface + */ +interface ControlInterface extends BlockInterface +{ + // +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/DataProviderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/DataProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..034e0fa56c6c448229160f3272384652ce70a158 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/DataProviderInterface.php @@ -0,0 +1,125 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent\DataProvider; + +/** + * Interface DataProviderInterface + */ +interface DataProviderInterface +{ + /** + * Get config data + * + * @return mixed + */ + public function getConfigData(); + + /** + * Set config data + * + * @param mixed $config + * @return void + */ + public function setConfigData($config); + + /** + * @return array + */ + public function getMeta(); + + /** + * @param string $fieldSetName + * @param string $fieldName + * @return array + */ + public function getFieldMetaInfo($fieldSetName, $fieldName); + + /** + * @param string $fieldSetName + * @return array + */ + public function getFieldsMetaInfo($fieldSetName); + + /** + * Get primary field name + * + * @return string + */ + public function getPrimaryFieldName(); + + /** + * Get field name in request + * + * @return string + */ + public function getRequestFieldName(); + + /** + * Get data + * + * @return mixed + */ + public function getData(); + + /** + * Add field to select + * + * @param string|array $field + * @param string|null $alias + * @return void + */ + public function addField($field, $alias = null); + + /** + * Add field filter to collection + * + * @param string|array $field + * @param string|int|array|null $condition + * @return void + */ + public function addFilter($field, $condition = null); + + /** + * Add ORDER BY to the end or to the beginning + * + * @param string $field + * @param string $direction + * @return void + */ + public function addOrder($field, $direction); + + /** + * Set Query limit + * + * @param int $offset + * @param int $size + * @return void + */ + public function setLimit($offset, $size); + + /** + * Removes field from select + * + * @param string|null $field + * @param bool $isAlias Alias identifier + * @return void + */ + public function removeField($field, $isAlias = false); + + /** + * Removes all fields from select + * + * @return void + */ + public function removeAllFields(); + + /** + * Retrieve count of loaded items + * + * @return int + */ + public function count(); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProviderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProviderInterface.php deleted file mode 100644 index 2ba4ce76daf8ea7d97421c6266b2b5bf6cd6cef2..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProviderInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\View\Element\UiComponent; - -/** - * Interface DataProviderInterface - * @package Magento\Framework\View\Element\UiComponent - */ -interface DataProviderInterface -{ - /** - * Get meta data - * - * @return array - */ - public function getMeta(); - - /** - * Get data - * - * @return array - */ - public function getData(); -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataSourceInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataSourceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d2d8f67167ab159d90b297f56935461f32481031 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataSourceInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent; + +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface DataSourceInterface + */ +interface DataSourceInterface extends UiComponentInterface +{ + /** + * @return DataProviderInterface + */ + public function getDataProvider(); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/JsConfigInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/JsConfigInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0826398d684042927ad8675b0cc6ae75cf68c7e2 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/JsConfigInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface JsConfigInterface + */ +interface JsConfigInterface extends UiComponentInterface +{ + /** + * Get JS config + * + * @return array|string + */ + public function getJsConfig(); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/LayoutInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/LayoutInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d5d98ecace047ea3ac1587a5f45ceca14fd1992d --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/LayoutInterface.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\UiComponent; + +use Magento\Framework\View\Element\UiComponentInterface; + +/** + * Interface LayoutInterface + */ +interface LayoutInterface +{ + const SECTIONS_KEY = 'sections'; + + const AREAS_KEY = 'areas'; + + const GROUPS_KEY = 'groups'; + + const ELEMENTS_KEY = 'elements'; + + const DATA_SOURCE_KEY = 'data_source'; + + /** + * @param UiComponentInterface $component + * @return array + */ + public function build(UiComponentInterface $component); +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php index 48239e9c92261b3b62ae5e0e19b942f2ff21fd72..a1b37315a3a1c632053ea0f39b5766151ac61796 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php @@ -6,9 +6,11 @@ namespace Magento\Framework\View\Element; use Magento\Framework\Object; -use Magento\Framework\View\Element\UiComponent\Context as RenderContext; -use Magento\Framework\View\LayoutFactory; -use Magento\Framework\View\LayoutInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Data\Argument\InterpreterInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\Config\ManagerInterface; /** * Class UiComponentFactory @@ -16,172 +18,154 @@ use Magento\Framework\View\LayoutInterface; class UiComponentFactory extends Object { /** - * Ui element view + * Object manager * - * @var UiComponentInterface + * @var ObjectManagerInterface */ - protected $view; + protected $objectManager; /** - * Render context + * UI component manager * - * @var RenderContext + * @var ManagerInterface */ - protected $renderContext; + protected $componentManager; /** - * Layout Interface + * Argument interpreter * - * @var \Magento\Framework\View\LayoutFactory + * @var InterpreterInterface */ - protected $layoutFactory; - - /** - * @var LayoutInterface - */ - protected $layout; - - /** - * @var bool - */ - protected $layoutLoaded = false; + protected $argumentInterpreter; /** * Constructor * - * @param RenderContext $renderContext - * @param LayoutFactory $layoutFactory + * @param ObjectManagerInterface $objectManager + * @param ManagerInterface $componentManager + * @param InterpreterInterface $argumentInterpreter * @param array $data */ public function __construct( - RenderContext $renderContext, - LayoutFactory $layoutFactory, + ObjectManagerInterface $objectManager, + ManagerInterface $componentManager, + InterpreterInterface $argumentInterpreter, array $data = [] ) { - $this->renderContext = $renderContext; - $this->renderContext->setRender($this); - $this->layoutFactory = $layoutFactory; + $this->objectManager = $objectManager; + $this->componentManager = $componentManager; + $this->argumentInterpreter = $argumentInterpreter; parent::__construct($data); } /** - * Get component name - * - * @return string - */ - public function getComponent() - { - return $this->getData('configuration/component'); - } - - /** - * Get layout handle - * - * @return string - */ - public function getLayoutHandle() - { - return $this->getData('configuration/name'); - } - - /** - * @param LayoutInterface $layout - * @return void - */ - public function setLayout(LayoutInterface $layout) - { - if (!$this->renderContext->getPageLayout()) { - $this->renderContext->setPageLayout($layout); - } - } - - /** - * Create Ui Component instance + * Create child components * - * @param string $componentName - * @param string $handleName - * @param array $arguments + * @param array $bundleComponents + * @param ContextInterface $renderContext + * @param string $identifier * @return UiComponentInterface */ - public function createUiComponent($componentName, $handleName, array $arguments = []) - { - if (!$this->layout) { - $this->renderContext->setNamespace($handleName); - $this->layout = $this->layoutFactory->create(); - $this->renderContext->setLayout($this->layout); - $this->layout->getUpdate()->addHandle('ui_components'); - $this->layout->getUpdate()->addHandle($handleName); - $this->loadLayout(); - $this->layoutLoaded = true; + protected function createChildComponent( + array $bundleComponents, + ContextInterface $renderContext, + $identifier + ) { + list($className, $arguments) = $this->argumentsResolver($identifier, $bundleComponents); + if (isset($arguments['data']['disabled']) && $arguments['data']['disabled'] === 'true') { + return null; } - - $view = $this->getUiElementView($componentName); - $view->update($arguments); - if ($this->layoutLoaded) { - $this->prepare($view); + $components = []; + foreach ($bundleComponents['children'] as $childrenIdentifier => $childrenData) { + $children = $this->createChildComponent( + $childrenData, + $renderContext, + $childrenIdentifier + ); + $components[$childrenIdentifier] = $children; + } + $components = array_filter($components); + $arguments['components'] = $components; + if (!isset($arguments['context'])) { + $arguments['context'] = $renderContext; } - return $view; + return $this->objectManager->create($className, $arguments); } /** - * Prepare UI Component data + * Resolve arguments * - * @param object $view - * @return void + * @param string $identifier + * @param array $componentData + * @return array */ - protected function prepare($view) + protected function argumentsResolver($identifier, array $componentData) { - if ($view instanceof UiComponentInterface) { - $view->prepare(); + $attributes = $componentData[ManagerInterface::COMPONENT_ATTRIBUTES_KEY]; + $className = $attributes['class']; + unset($attributes['class']); + $arguments = []; + foreach ($componentData[ManagerInterface::COMPONENT_ARGUMENTS_KEY] as $name => $argument) { + $arguments[$name] = $this->argumentInterpreter->evaluate($argument); } - foreach ($view->getLayout()->getChildNames($view->getNameInLayout()) as $childAlias) { - $name = $view->getLayout()->getChildName($view->getNameInLayout(), $childAlias); - if ($view->getLayout()->isContainer($name)) { - foreach ($view->getLayout()->getChildNames($name) as $childName) { - $child = $view->getLayout()->getBlock($childName); - $this->prepare($child); - } - } else { - $child = $view->getChildBlock($childAlias); - if ($child) { - $this->prepare($child); - } - } + + if (!isset($arguments['data'])) { + $arguments['data'] = []; } + + $arguments['data'] = array_merge($arguments['data'], ['name' => $identifier], $attributes); + return [$className, $arguments]; } /** - * Get UI Element View + * Create component object * - * @param string $uiElementName + * @param string $identifier + * @param string $name + * @param array $arguments * @return UiComponentInterface - * @throws \InvalidArgumentException + * @throws \Magento\Framework\Exception\LocalizedException */ - public function getUiElementView($uiElementName) + public function create($identifier, $name = null, array $arguments = []) { - /** @var UiComponentInterface $view */ - $view = $this->layout->getBlock($uiElementName); - if (!$view instanceof UiComponentInterface) { - throw new \InvalidArgumentException( - sprintf( - 'UI Element "%s" must implement \Magento\Framework\View\Element\UiComponentInterface', - $uiElementName - ) + if ($name === null) { + $bundleComponents = $this->componentManager->prepareData($identifier)->getData($identifier); + if (empty($bundleComponents)) { + throw new LocalizedException(new \Magento\Framework\Phrase('You use an empty set.')); + } + list($className, $componentArguments) = $this->argumentsResolver( + $identifier, + $bundleComponents[$identifier] ); - } - return $view; - } + $componentArguments = array_merge($componentArguments, $arguments); + if (!isset($componentArguments['context'])) { + throw new LocalizedException(new \Magento\Framework\Phrase('Context, is required argument.')); + } + $componentContext = $componentArguments['context']; + $components = []; + foreach ($bundleComponents[$identifier]['children'] as $childrenIdentifier => $childrenData) { + $children = $this->createChildComponent( + $childrenData, + $componentContext, + $childrenIdentifier + ); + $components[$childrenIdentifier] = $children; + } + $components = array_filter($components); + $componentArguments['components'] = $components; - /** - * Load layout - * - * @return void - */ - protected function loadLayout() - { - $this->layout->getUpdate()->load(); - $this->layout->generateXml(); - $this->layout->generateElements(); + /** @var \Magento\Framework\View\Element\UiComponentInterface $component */ + $component = $this->objectManager->create($className, array_merge($componentArguments, $arguments)); + + return $component; + } else { + $defaultData = $this->componentManager->createRawComponentData($name); + list($className, $componentArguments) = $this->argumentsResolver($identifier, $defaultData); + /** @var \Magento\Framework\View\Element\UiComponentInterface $component */ + $component = $this->objectManager->create($className, array_merge($componentArguments, $arguments)); + + return $component; + } } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php index 343f82b40d49eda567334bda03af72991cfe1ef6..a38823e7f0b14933a9fad1a2eaece9386d79f818 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php @@ -5,98 +5,105 @@ */ namespace Magento\Framework\View\Element; -use Magento\Framework\View\Element\UiComponent\Context as RenderContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; /** - * Class UiComponentInterface + * Interface UiComponentInterface */ interface UiComponentInterface extends BlockInterface { /** - * Update component data + * Get component instance name * - * @param array $arguments * @return string */ - public function update(array $arguments = []); + public function getName(); /** - * Prepare component data + * Get component name * - * @return void + * @return string */ - public function prepare(); + public function getComponentName(); /** * Render component * - * @param array $data * @return string */ - public function render(array $data = []); + public function render(); /** - * Render label + * Add component * - * @return mixed|string + * @param string $name + * @param UiComponentInterface $component + * @return void */ - public function renderLabel(); + public function addComponent($name, UiComponentInterface $component); /** - * Getting template for rendering content - * - * @return string|false + * @param string $name + * @return UiComponentInterface */ - public function getContentTemplate(); + public function getComponent($name); /** - * Getting template for rendering label + * Get child components * - * @return string|false + * @return UiComponentInterface[] */ - public function getLabelTemplate(); + public function getChildComponents(); /** - * Getting instance name + * Get template * * @return string */ - public function getName(); + public function getTemplate(); /** - * Getting parent name component instance + * Get component context * - * @return string + * @return ContextInterface */ - public function getParentName(); + public function getContext(); /** - * Get render context + * Render child component * - * @return RenderContext + * @param string $name + * @return string */ - public function getRenderContext(); + public function renderChildComponent($name); /** - * Get elements + * Component data setter * - * @return UiComponentInterface[] + * @param string|array $key + * @param mixed $value + * @return void */ - public function getElements(); + public function setData($key, $value = null); /** - * Set elements + * Component data getter * - * @param array $elements + * @param string $key + * @param string|int $index * @return mixed */ - public function setElements(array $elements); + public function getData($key = '', $index = null); + + /** + * @return array + */ + public function getDataSourceData(); /** - * Get configuration builder + * Prepare component configuration * - * @return ConfigBuilderInterface + * @return void */ - public function getConfigBuilder(); + public function prepare(); } diff --git a/lib/internal/Magento/Framework/View/Element/UiElementFactory.php b/lib/internal/Magento/Framework/View/Element/UiElementFactory.php deleted file mode 100644 index e6ae25787d59439286227694e66b78bab2ee4ad9..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiElementFactory.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\View\Element; - -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\View\Element\UiComponent\Context as UiContext; - -/** - * Class UiElementFactory - */ -class UiElementFactory -{ - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * @var UiContext - */ - protected $context; - - /** - * Constructor - * - * @param ObjectManagerInterface $objectManager - * @param UiContext $context - */ - public function __construct(ObjectManagerInterface $objectManager, UiContext $context) - { - $this->objectManager = $objectManager; - $this->context = $context; - } - - /** - * Create data provider - * - * @param string $elementName - * @param array $data - * @return bool|BlockInterface - * @throws \Exception - */ - public function create($elementName, array $data = []) - { - if ('text' == $elementName) { - $elementName = 'input'; - } - $block = $this->context->getLayout()->getBlock($elementName); - if (!$block) { - throw new \Exception('Can not find block of element ' . $elementName); - } - $newBlock = clone $block; - $newBlock->addData($data); - return $newBlock; - } -} diff --git a/lib/internal/Magento/Framework/View/Layout.php b/lib/internal/Magento/Framework/View/Layout.php index 6c857548d18ed329d6767bbc6f35684f8205e059..da8130891b3b05e624f358c2f0fe5b1b52d7444d 100644 --- a/lib/internal/Magento/Framework/View/Layout.php +++ b/lib/internal/Magento/Framework/View/Layout.php @@ -23,6 +23,12 @@ use Magento\Framework\View\Layout\ScheduledStructure; */ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Framework\View\LayoutInterface { + + /** + * Empty layout xml + */ + const LAYOUT_NODE = '<layout/>'; + /** * Layout Update module * @@ -173,7 +179,6 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra $cacheable = true ) { $this->_elementClass = 'Magento\Framework\View\Layout\Element'; - $this->setXml(simplexml_load_string('<layout/>', $this->_elementClass)); $this->_renderingOutput = new \Magento\Framework\Object(); $this->_processorFactory = $processorFactory; @@ -188,8 +193,6 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra $this->readerContextFactory = $readerContextFactory; $this->generatorContextFactory = $generatorContextFactory; - - $this->readerContext = $this->readerContextFactory->create(); } /** @@ -248,7 +251,7 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra $this->_update = null; } $this->_blocks = []; - $this->_xml = null; + parent::__destruct(); } /** @@ -278,14 +281,6 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra return $this; } - /** - * @return Layout\Reader\Context - */ - public function getReaderContext() - { - return $this->readerContext; - } - /** * Create structure of elements from the loaded XML configuration * @@ -297,13 +292,12 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra $cacheId = 'structure_' . $this->getUpdate()->getCacheId(); $result = $this->cache->load($cacheId); if ($result) { - /** @var Layout\Reader\Context $readerContext */ $this->readerContext = unserialize($result); } else { \Magento\Framework\Profiler::start('build_structure'); - $this->readerPool->interpret($this->readerContext, $this->getNode()); + $this->readerPool->interpret($this->getReaderContext(), $this->getNode()); \Magento\Framework\Profiler::stop('build_structure'); - $this->cache->save(serialize($this->readerContext), $cacheId, $this->getUpdate()->getHandles()); + $this->cache->save(serialize($this->getReaderContext()), $cacheId, $this->getUpdate()->getHandles()); } $generatorContext = $this->generatorContextFactory->create( @@ -314,7 +308,7 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra ); \Magento\Framework\Profiler::start('generate_elements'); - $this->generatorPool->process($this->readerContext, $generatorContext); + $this->generatorPool->process($this->getReaderContext(), $generatorContext); \Magento\Framework\Profiler::stop('generate_elements'); $this->addToOutputRootContainers(); @@ -1035,7 +1029,7 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra public function isCacheable() { $this->build(); - $cacheableXml = !(bool)count($this->_xml->xpath('//' . Element::TYPE_BLOCK . '[@cacheable="false"]')); + $cacheableXml = !(bool)count($this->getXml()->xpath('//' . Element::TYPE_BLOCK . '[@cacheable="false"]')); return $this->cacheable && $cacheableXml; } @@ -1060,4 +1054,30 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra $this->isPrivate = (bool)$isPrivate; return $this; } + + /** + * Getter and lazy loader for xml element + * + * @return \Magento\Framework\Simplexml\Element + */ + protected function getXml() + { + if (!$this->_xml) { + $this->setXml(simplexml_load_string(self::LAYOUT_NODE, $this->_elementClass)); + } + return $this->_xml; + } + + /** + * Getter and lazy loader for reader context + * + * @return Layout\Reader\Context + */ + public function getReaderContext() + { + if (!$this->readerContext) { + $this->readerContext = $this->readerContextFactory->create(); + } + return $this->readerContext; + } } diff --git a/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php b/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php index 7697660afc02f2bd378e632c53d2fc4701976dc0..fd4bca2122cda5a66b55053ec86018c8495cea12 100644 --- a/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php +++ b/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php @@ -41,7 +41,13 @@ class Parser if (!$this->converter) { $arrayNodeConfig = new ArrayNodeConfig( new NodePathMatcher(), - ['argument/param' => 'name', 'argument(/item)+' => 'name', 'argument(/item)+/param' => 'name'], + [ + 'argument/param' => 'name', + 'argument(/item)+' => 'name', + 'argument(/item)+/param' => 'name', + 'argument(/argument)+' => 'name', + 'argument((/argument)+(/item)+)+' => 'name', + ], ['argument/updater'] ); $this->converter = new FlatConverter($arrayNodeConfig); diff --git a/lib/internal/Magento/Framework/View/Layout/Element.php b/lib/internal/Magento/Framework/View/Layout/Element.php index 01e58372cec32bb6781a007019b9c6f37710c336..3ea80ec098168716b3d5ec83c2273f3db890b07a 100644 --- a/lib/internal/Magento/Framework/View/Layout/Element.php +++ b/lib/internal/Magento/Framework/View/Layout/Element.php @@ -37,7 +37,7 @@ class Element extends \Magento\Framework\Simplexml\Element const TYPE_MOVE = 'move'; - const TYPE_UI_COMPONENT = 'ui_component'; + const TYPE_UI_COMPONENT = 'uiComponent'; const TYPE_HEAD = 'head'; diff --git a/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php b/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php index 0356d93d04c868518ad389136162898e15a3201e..d5a8fcda61c2a164f1da15f4f9f3482112d18fe1 100644 --- a/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php +++ b/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php @@ -5,45 +5,63 @@ */ namespace Magento\Framework\View\Layout\Generator; -use Magento\Framework\Data\Argument\InterpreterInterface; -use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\View\Layout; +use Magento\Framework\View\Element\BlockFactory; +use Magento\Framework\View\Layout\Data\Structure; +use Magento\Framework\View\Layout\GeneratorInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Data\Argument\InterpreterInterface; +use Magento\Framework\View\Element\UiComponent\ContainerInterface; +use Magento\Framework\View\Layout\Reader\Context as ReaderContext; +use Magento\Framework\View\Layout\Generator\Context as GeneratorContext; +use Magento\Framework\View\Element\UiComponent\ContextFactory as UiComponentContextFactory; +use Magento\Framework\View\LayoutInterface; -class UiComponent implements Layout\GeneratorInterface +/** + * Class UiComponent + */ +class UiComponent implements GeneratorInterface { /** * Generator type */ - const TYPE = 'ui_component'; + const TYPE = 'uiComponent'; /** - * @var \Magento\Framework\View\Element\UiComponentFactory + * Block container for components + */ + const CONTAINER = 'Magento\Framework\View\Element\UiComponent\ContainerInterface'; + + /** + * @var UiComponentFactory */ protected $uiComponentFactory; /** - * @var \Magento\Framework\Data\Argument\InterpreterInterface + * @var UiComponentContextFactory */ - protected $argumentInterpreter; + protected $contextFactory; /** * Constructor * * @param UiComponentFactory $uiComponentFactory - * @param \Magento\Framework\Data\Argument\InterpreterInterface $argumentInterpreter + * @param BlockFactory $blockFactory + * @param UiComponentContextFactory $contextFactory */ public function __construct( UiComponentFactory $uiComponentFactory, - InterpreterInterface $argumentInterpreter + BlockFactory $blockFactory, + UiComponentContextFactory $contextFactory ) { $this->uiComponentFactory = $uiComponentFactory; - $this->argumentInterpreter = $argumentInterpreter; + $this->blockFactory = $blockFactory; + $this->contextFactory = $contextFactory; } /** * {@inheritdoc} - * - * @return string */ public function getType() { @@ -53,11 +71,11 @@ class UiComponent implements Layout\GeneratorInterface /** * Creates UI Component object based on scheduled data and add it to the layout * - * @param Layout\Reader\Context $readerContext - * @param Context $generatorContext + * @param ReaderContext $readerContext + * @param GeneratorContext $generatorContext * @return $this */ - public function process(Layout\Reader\Context $readerContext, Layout\Generator\Context $generatorContext) + public function process(ReaderContext $readerContext, GeneratorContext $generatorContext) { $scheduledStructure = $readerContext->getScheduledStructure(); $scheduledElements = $scheduledStructure->getElements(); @@ -66,18 +84,16 @@ class UiComponent implements Layout\GeneratorInterface } $structure = $generatorContext->getStructure(); $layout = $generatorContext->getLayout(); - $this->uiComponentFactory->setLayout($layout); + + // Instantiate blocks and collect all actions data /** @var $blocks \Magento\Framework\View\Element\AbstractBlock[] */ $blocks = []; - // Instantiate blocks and collect all actions data foreach ($scheduledElements as $elementName => $element) { - list($type, $data) = $element; - if ($type === self::TYPE) { - $block = $this->generateComponent($structure, $elementName, $data); - $blocks[$elementName] = $block; - $layout->setBlock($elementName, $block); - $scheduledStructure->unsetElement($elementName); - } + list(, $data) = $element; + $block = $this->generateComponent($structure, $elementName, $data, $layout); + $blocks[$elementName] = $block; + $layout->setBlock($elementName, $block); + $scheduledStructure->unsetElement($elementName); } return $this; @@ -86,35 +102,49 @@ class UiComponent implements Layout\GeneratorInterface /** * Create component object * - * @param \Magento\Framework\View\Layout\Data\Structure $structure + * @param Structure $structure * @param string $elementName * @param string $data - * @return \Magento\Framework\View\Element\UiComponentInterface + * @param LayoutInterface $layout + * @return ContainerInterface */ - protected function generateComponent(Layout\Data\Structure $structure, $elementName, $data) + protected function generateComponent(Structure $structure, $elementName, $data, LayoutInterface $layout) { $attributes = $data['attributes']; if (!empty($attributes['group'])) { $structure->addToParentGroup($elementName, $attributes['group']); } - $arguments = empty($data['arguments']) ? [] : $this->evaluateArguments($data['arguments']); - $componentName = isset($attributes['component']) ? $attributes['component'] : ''; - $uiComponent = $this->uiComponentFactory->createUiComponent($componentName, $elementName, $arguments); - return $uiComponent; + + $context = $this->contextFactory->create([ + 'namespace' => $elementName, + 'pageLayout' => $layout + ]); + + $component = $this->uiComponentFactory->create($elementName, null, [ + 'context' => $context + ]); + $this->prepareComponent($component); + + /** @var ContainerInterface $blockContainer */ + $blockContainer = $this->blockFactory->createBlock(static::CONTAINER, ['component' => $component]); + + return $blockContainer; } /** - * Compute and return argument values + * Call prepare method in the component UI * - * @param array $arguments - * @return array + * @param UiComponentInterface $component + * @return void */ - protected function evaluateArguments(array $arguments) + protected function prepareComponent(UiComponentInterface $component) { - $result = []; - foreach ($arguments as $argumentName => $argumentData) { - $result[$argumentName] = $this->argumentInterpreter->evaluate($argumentData); + $childComponents = $component->getChildComponents(); + if (!empty($childComponents)) { + foreach ($childComponents as $child) { + $this->prepareComponent($child); + } } - return $result; + $component->prepare(); } } diff --git a/lib/internal/Magento/Framework/View/Layout/Proxy.php b/lib/internal/Magento/Framework/View/Layout/Proxy.php index 8c399f4e4161a7f847b4f22db49e7e97e8528ef2..95220e34913df356a84e427d9d72e04f5c73b6ac 100644 --- a/lib/internal/Magento/Framework/View/Layout/Proxy.php +++ b/lib/internal/Magento/Framework/View/Layout/Proxy.php @@ -6,8 +6,7 @@ namespace Magento\Framework\View\Layout; /** - * Proxy class for \Magento\Framework\View\Layout - * + * Proxy class for @see \Magento\Framework\View\Layout * @SuppressWarnings(PHPMD.ExcessivePublicCount) */ class Proxy extends \Magento\Framework\View\Layout @@ -17,42 +16,44 @@ class Proxy extends \Magento\Framework\View\Layout * * @var \Magento\Framework\ObjectManagerInterface */ - protected $objectManager; + protected $_objectManager = null; /** * Proxied instance name * * @var string */ - protected $instanceName; + protected $_instanceName = null; /** * Proxied instance * * @var \Magento\Framework\View\Layout */ - protected $subject; + protected $_subject = null; /** * Instance shareability flag * * @var bool */ - protected $isShared; + protected $_isShared = null; /** + * Proxy constructor + * * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param string $instanceName * @param bool $shared */ public function __construct( \Magento\Framework\ObjectManagerInterface $objectManager, - $instanceName = 'Magento\Framework\View\Layout', + $instanceName = '\\Magento\\Framework\\View\\Layout', $shared = true ) { - $this->objectManager = $objectManager; - $this->instanceName = $instanceName; - $this->isShared = $shared; + $this->_objectManager = $objectManager; + $this->_instanceName = $instanceName; + $this->_isShared = $shared; } /** @@ -70,7 +71,7 @@ class Proxy extends \Magento\Framework\View\Layout */ public function __wakeup() { - $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance(); } /** @@ -80,7 +81,7 @@ class Proxy extends \Magento\Framework\View\Layout */ public function __clone() { - $this->subject = clone $this->getSubject(); + $this->_subject = clone $this->_getSubject(); } /** @@ -88,415 +89,334 @@ class Proxy extends \Magento\Framework\View\Layout * * @return \Magento\Framework\View\Layout */ - protected function getSubject() + protected function _getSubject() { - if (!$this->subject) { - $this->subject = true === $this->isShared - ? $this->objectManager->get($this->instanceName) - : $this->objectManager->create($this->instanceName); + if (!$this->_subject) { + $this->_subject = true === $this->_isShared + ? $this->_objectManager->get($this->_instanceName) + : $this->_objectManager->create($this->_instanceName); } - return $this->subject; + return $this->_subject; } /** - * Retrieve the layout update instance - * - * @return \Magento\Framework\View\Layout\ProcessorInterface + * {@inheritdoc} + */ + public function setGeneratorPool(\Magento\Framework\View\Layout\GeneratorPool $generatorPool) + { + return $this->_getSubject()->setGeneratorPool($generatorPool); + } + + /** + * {@inheritdoc} + */ + public function setBuilder(\Magento\Framework\View\Layout\BuilderInterface $builder) + { + return $this->_getSubject()->setBuilder($builder); + } + + /** + * {@inheritdoc} + */ + public function publicBuild() + { + $this->_getSubject()->publicBuild(); + } + + /** + * {@inheritdoc} */ public function getUpdate() { - return $this->getSubject()->getUpdate(); + return $this->_getSubject()->getUpdate(); } /** - * Layout xml generation - * - * @return $this + * {@inheritdoc} */ public function generateXml() { - return $this->getSubject()->generateXml(); + return $this->_getSubject()->generateXml(); } /** - * Create structure of elements from the loaded XML configuration - * - * @return void + * {@inheritdoc} */ public function generateElements() { - $this->getSubject()->generateElements(); + $this->_getSubject()->generateElements(); } /** - * Get child block if exists - * - * @param string $parentName - * @param string $alias - * @return bool|\Magento\Framework\View\Element\AbstractBlock + * {@inheritdoc} */ public function getChildBlock($parentName, $alias) { - return $this->getSubject()->getChildBlock($parentName, $alias); + return $this->_getSubject()->getChildBlock($parentName, $alias); } /** - * Set child element into layout structure - * - * @param string $parentName - * @param string $elementName - * @param string $alias - * @return $this + * {@inheritdoc} */ public function setChild($parentName, $elementName, $alias) { - return $this->getSubject()->setChild($parentName, $elementName, $alias); + return $this->_getSubject()->setChild($parentName, $elementName, $alias); } /** - * Reorder a child of a specified element - * - * If $offsetOrSibling is null, it will put the element to the end - * If $offsetOrSibling is numeric (integer) value, it will put the element after/before specified position - * Otherwise -- after/before specified sibling - * - * @param string $parentName - * @param string $childName - * @param string|int|null $offsetOrSibling - * @param bool $after - * @return void + * {@inheritdoc} */ public function reorderChild($parentName, $childName, $offsetOrSibling, $after = true) { - $this->getSubject()->reorderChild($parentName, $childName, $offsetOrSibling, $after); + $this->_getSubject()->reorderChild($parentName, $childName, $offsetOrSibling, $after); } /** - * Remove child element from parent - * - * @param string $parentName - * @param string $alias - * @return $this + * {@inheritdoc} */ public function unsetChild($parentName, $alias) { - return $this->getSubject()->unsetChild($parentName, $alias); + return $this->_getSubject()->unsetChild($parentName, $alias); } /** - * Get list of child names - * - * @param string $parentName - * @return array + * {@inheritdoc} */ public function getChildNames($parentName) { - return $this->getSubject()->getChildNames($parentName); + return $this->_getSubject()->getChildNames($parentName); } /** - * Get list of child blocks - * - * Returns associative array of <alias> => <block instance> - * - * @param string $parentName - * @return array + * {@inheritdoc} */ public function getChildBlocks($parentName) { - return $this->getSubject()->getChildBlocks($parentName); + return $this->_getSubject()->getChildBlocks($parentName); } /** - * Get child name by alias - * - * @param string $parentName - * @param string $alias - * @return bool|string + * {@inheritdoc} */ public function getChildName($parentName, $alias) { - return $this->getSubject()->getChildName($parentName, $alias); + return $this->_getSubject()->getChildName($parentName, $alias); } /** - * Find an element in layout, render it and return string with its output - * - * @param string $name - * @param bool $useCache - * @return string + * {@inheritdoc} */ public function renderElement($name, $useCache = true) { - return $this->getSubject()->renderElement($name, $useCache); + return $this->_getSubject()->renderElement($name, $useCache); } /** - * Add element to parent group - * - * @param string $blockName - * @param string $parentGroupName - * @return bool + * {@inheritdoc} + */ + public function renderNonCachedElement($name) + { + return $this->_getSubject()->renderNonCachedElement($name); + } + + /** + * {@inheritdoc} */ public function addToParentGroup($blockName, $parentGroupName) { - return $this->getSubject()->addToParentGroup($blockName, $parentGroupName); + return $this->_getSubject()->addToParentGroup($blockName, $parentGroupName); } /** - * Get element names for specified group - * - * @param string $blockName - * @param string $groupName - * @return array + * {@inheritdoc} */ public function getGroupChildNames($blockName, $groupName) { - return $this->getSubject()->getGroupChildNames($blockName, $groupName); + return $this->_getSubject()->getGroupChildNames($blockName, $groupName); } /** - * Check if element exists in layout structure - * - * @param string $name - * @return bool + * {@inheritdoc} */ public function hasElement($name) { - return $this->getSubject()->hasElement($name); + return $this->_getSubject()->hasElement($name); } /** - * Get property value of an element - * - * @param string $name - * @param string $attribute - * @return mixed + * {@inheritdoc} */ public function getElementProperty($name, $attribute) { - return $this->getSubject()->getElementProperty($name, $attribute); + return $this->_getSubject()->getElementProperty($name, $attribute); } /** - * Whether specified element is a block - * - * @param string $name - * @return bool + * {@inheritdoc} */ public function isBlock($name) { - return $this->getSubject()->isBlock($name); + return $this->_getSubject()->isBlock($name); } /** - * Checks if element with specified name is container - * - * @param string $name - * @return bool + * {@inheritdoc} + */ + public function isUiComponent($name) + { + return $this->_getSubject()->isUiComponent($name); + } + + /** + * {@inheritdoc} */ public function isContainer($name) { - return $this->getSubject()->isContainer($name); + return $this->_getSubject()->isContainer($name); } /** - * Whether the specified element may be manipulated externally - * - * @param string $name - * @return bool + * {@inheritdoc} */ public function isManipulationAllowed($name) { - return $this->getSubject()->isManipulationAllowed($name); + return $this->_getSubject()->isManipulationAllowed($name); } /** - * Save block in blocks registry - * - * @param string $name - * @param \Magento\Framework\View\Element\AbstractBlock $block - * @return $this + * {@inheritdoc} */ public function setBlock($name, $block) { - return $this->getSubject()->setBlock($name, $block); + return $this->_getSubject()->setBlock($name, $block); } /** - * Remove block from registry - * - * @param string $name - * @return $this + * {@inheritdoc} */ public function unsetElement($name) { - return $this->getSubject()->unsetElement($name); + return $this->_getSubject()->unsetElement($name); } /** - * Block Factory - * - * @param string $type - * @param string $name - * @param array $attributes - * @return \Magento\Framework\View\Element\AbstractBlock + * {@inheritdoc} */ - public function createBlock($type, $name = '', array $attributes = []) + public function createBlock($type, $name = '', array $arguments = []) { - return $this->getSubject()->createBlock($type, $name, $attributes); + return $this->_getSubject()->createBlock($type, $name, $arguments); } /** - * Add a block to registry, create new object if needed - * - * @param string|\Magento\Framework\View\Element\AbstractBlock $block - * @param string $name - * @param string $parent - * @param string $alias - * @return \Magento\Framework\View\Element\AbstractBlock + * {@inheritdoc} */ public function addBlock($block, $name = '', $parent = '', $alias = '') { - return $this->getSubject()->addBlock($block, $name, $parent, $alias); + return $this->_getSubject()->addBlock($block, $name, $parent, $alias); } /** - * Insert container into layout structure - * - * @param string $name - * @param string $label - * @param array $options - * @param string $parent - * @param string $alias - * @return void + * {@inheritdoc} */ public function addContainer($name, $label, array $options = [], $parent = '', $alias = '') { - $this->getSubject()->addContainer($name, $label, $options, $parent, $alias); + $this->_getSubject()->addContainer($name, $label, $options, $parent, $alias); } /** - * Rename element in layout and layout structure - * - * @param string $oldName - * @param string $newName - * @return bool + * {@inheritdoc} */ public function renameElement($oldName, $newName) { - return $this->getSubject()->renameElement($oldName, $newName); + return $this->_getSubject()->renameElement($oldName, $newName); } /** - * Retrieve all blocks from registry as array - * - * @return array + * {@inheritdoc} */ public function getAllBlocks() { - return $this->getSubject()->getAllBlocks(); + return $this->_getSubject()->getAllBlocks(); } /** - * Get block object by name - * - * @param string $name - * @return \Magento\Framework\View\Element\AbstractBlock|bool + * {@inheritdoc} */ public function getBlock($name) { - return $this->getSubject()->getBlock($name); + return $this->_getSubject()->getBlock($name); } /** - * Gets parent name of an element with specified name - * - * @param string $childName - * @return bool|string + * {@inheritdoc} + */ + public function getUiComponent($name) + { + return $this->_getSubject()->getUiComponent($name); + } + + /** + * {@inheritdoc} */ public function getParentName($childName) { - return $this->getSubject()->getParentName($childName); + return $this->_getSubject()->getParentName($childName); } /** - * Get element alias by name - * - * @param string $name - * @return bool|string + * {@inheritdoc} */ public function getElementAlias($name) { - return $this->getSubject()->getElementAlias($name); + return $this->_getSubject()->getElementAlias($name); } /** - * Add an element to output - * - * @param string $name - * @return $this + * {@inheritdoc} */ public function addOutputElement($name) { - return $this->getSubject()->addOutputElement($name); + return $this->_getSubject()->addOutputElement($name); } /** - * Remove an element from output - * - * @param string $name - * @return $this + * {@inheritdoc} */ public function removeOutputElement($name) { - return $this->getSubject()->removeOutputElement($name); + return $this->_getSubject()->removeOutputElement($name); } /** - * Get all blocks marked for output - * - * @return string + * {@inheritdoc} */ public function getOutput() { - return $this->getSubject()->getOutput(); + return $this->_getSubject()->getOutput(); } /** - * Retrieve messages block - * - * @return \Magento\Framework\View\Element\Messages + * {@inheritdoc} */ public function getMessagesBlock() { - return $this->getSubject()->getMessagesBlock(); + return $this->_getSubject()->getMessagesBlock(); } /** - * Get block singleton - * - * @param string $type - * @throws \Magento\Framework\Exception\LocalizedException - * @return \Magento\Framework\App\Helper\AbstractHelper + * {@inheritdoc} */ public function getBlockSingleton($type) { - return $this->getSubject()->getBlockSingleton($type); + return $this->_getSubject()->getBlockSingleton($type); } /** - * @param string $namespace - * @param string $staticType - * @param string $dynamicType - * @param string $type - * @param string $template - * @param array $data - * @return $this + * {@inheritdoc} */ public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $type, $template, $data = []) { - return $this->getSubject()->addAdjustableRenderer( + return $this->_getSubject()->addAdjustableRenderer( $namespace, $staticType, $dynamicType, @@ -507,394 +427,298 @@ class Proxy extends \Magento\Framework\View\Layout } /** - * Get renderer options - * - * @param string $namespace - * @param string $staticType - * @param string $dynamicType - * @return array|null + * {@inheritdoc} */ public function getRendererOptions($namespace, $staticType, $dynamicType) { - return $this->getSubject()->getRendererOptions($namespace, $staticType, $dynamicType); + return $this->_getSubject()->getRendererOptions($namespace, $staticType, $dynamicType); } /** - * Execute renderer - * - * @param string $namespace - * @param string $staticType - * @param string $dynamicType - * @param array $data - * @return void + * {@inheritdoc} */ public function executeRenderer($namespace, $staticType, $dynamicType, $data = []) { - $this->getSubject()->executeRenderer($namespace, $staticType, $dynamicType, $data); + $this->_getSubject()->executeRenderer($namespace, $staticType, $dynamicType, $data); } /** - * Init messages by message storage(s), loading and adding messages to layout messages block - * - * @param string|array $messageGroups - * @return void + * {@inheritdoc} */ public function initMessages($messageGroups = []) { - $this->getSubject()->initMessages($messageGroups); + $this->_getSubject()->initMessages($messageGroups); } /** - * Check is exists non-cacheable layout elements - * - * @return bool + * {@inheritdoc} */ public function isCacheable() { - return $this->getSubject()->isCacheable(); + return $this->_getSubject()->isCacheable(); } /** - * Check is exists non-cacheable layout elements - * - * @return bool + * {@inheritdoc} */ public function isPrivate() { - return $this->getSubject()->isPrivate(); + return $this->_getSubject()->isPrivate(); } /** - * Mark layout as private - * - * @param bool $isPrivate - * @return $this + * {@inheritdoc} */ public function setIsPrivate($isPrivate = true) { - return $this->getSubject()->setIsPrivate($isPrivate); + return $this->_getSubject()->setIsPrivate($isPrivate); } /** - * Sets xml for this configuration - * - * @param \Magento\Framework\Simplexml\Element $node - * @return $this + * {@inheritdoc} + */ + public function getReaderContext() + { + return $this->_getSubject()->getReaderContext(); + } + + /** + * {@inheritdoc} */ public function setXml(\Magento\Framework\Simplexml\Element $node) { - return $this->getSubject()->setXml($node); + return $this->_getSubject()->setXml($node); } /** - * Returns node found by the $path - * - * @param string $path - * @return \Magento\Framework\Simplexml\Element|bool - * @see \Magento\Framework\Simplexml\Element::descend + * {@inheritdoc} */ public function getNode($path = null) { - return $this->getSubject()->getNode($path); + return $this->_getSubject()->getNode($path); } /** - * Returns nodes found by xpath expression - * - * @param string $xpath - * @return \SimpleXMLElement[]|bool + * {@inheritdoc} */ public function getXpath($xpath) { - return $this->getSubject()->getXpath($xpath); + return $this->_getSubject()->getXpath($xpath); } /** - * Set cache - * - * @param \Magento\Framework\Simplexml\Config\Cache\AbstractCache $cache - * @return $this + * {@inheritdoc} */ public function setCache($cache) { - return $this->getSubject()->setCache($cache); + return $this->_getSubject()->setCache($cache); } /** - * Return cache - * - * @return \Magento\Framework\Simplexml\Config\Cache\AbstractCache + * {@inheritdoc} */ public function getCache() { - return $this->getSubject()->getCache(); + return $this->_getSubject()->getCache(); } /** - * Set whether cache is saved - * - * @param boolean $flag - * @return $this + * {@inheritdoc} */ public function setCacheSaved($flag) { - return $this->getSubject()->setCacheSaved($flag); + return $this->_getSubject()->setCacheSaved($flag); } /** - * Return whether cache is saved - * - * @return bool - * - * @SuppressWarnings(PHPMD.BooleanGetMethodName) + * {@inheritdoc} */ public function getCacheSaved() { - return $this->getSubject()->getCacheSaved(); + return $this->_getSubject()->getCacheSaved(); } /** - * Set cache ID - * - * @param string $id - * @return $this + * {@inheritdoc} */ public function setCacheId($id) { - return $this->getSubject()->setCacheId($id); + return $this->_getSubject()->setCacheId($id); } /** - * Return cache ID - * - * @return string + * {@inheritdoc} */ public function getCacheId() { - return $this->getSubject()->getCacheId(); + return $this->_getSubject()->getCacheId(); } /** - * Set cache tags - * - * @param array $tags - * @return $this + * {@inheritdoc} */ public function setCacheTags($tags) { - return $this->getSubject()->setCacheTags($tags); + return $this->_getSubject()->setCacheTags($tags); } /** - * Return cache tags - * - * @return array + * {@inheritdoc} */ public function getCacheTags() { - return $this->getSubject()->getCacheTags(); + return $this->_getSubject()->getCacheTags(); } /** - * Set cache lifetime - * - * @param int $lifetime - * @return $this + * {@inheritdoc} */ public function setCacheLifetime($lifetime) { - return $this->getSubject()->setCacheLifetime($lifetime); + return $this->_getSubject()->setCacheLifetime($lifetime); } /** - * Return cache lifetime - * - * @return int + * {@inheritdoc} */ public function getCacheLifetime() { - return $this->getSubject()->getCacheLifetime(); + return $this->_getSubject()->getCacheLifetime(); } /** - * Set cache checksum - * - * @param string $data - * @return $this + * {@inheritdoc} */ public function setCacheChecksum($data) { - return $this->getSubject()->setCacheChecksum($data); + return $this->_getSubject()->setCacheChecksum($data); } /** - * Update cache checksum - * - * @param string $data - * @return $this + * {@inheritdoc} */ public function updateCacheChecksum($data) { - return $this->getSubject()->updateCacheChecksum($data); + return $this->_getSubject()->updateCacheChecksum($data); } /** - * Return cache checksum - * - * @return string + * {@inheritdoc} */ public function getCacheChecksum() { - return $this->getSubject()->getCacheChecksum(); + return $this->_getSubject()->getCacheChecksum(); } /** - * Get cache checksum ID - * - * @return string + * {@inheritdoc} */ public function getCacheChecksumId() { - return $this->getSubject()->getCacheChecksumId(); + return $this->_getSubject()->getCacheChecksumId(); } /** - * Fetch cache checksum - * - * @return boolean + * {@inheritdoc} */ public function fetchCacheChecksum() { - return $this->getSubject()->fetchCacheChecksum(); + return $this->_getSubject()->fetchCacheChecksum(); } /** - * Validate cache checksum - * - * @return boolean + * {@inheritdoc} */ public function validateCacheChecksum() { - return $this->getSubject()->validateCacheChecksum(); + return $this->_getSubject()->validateCacheChecksum(); } /** - * Load cache - * - * @return boolean + * {@inheritdoc} */ public function loadCache() { - return $this->getSubject()->loadCache(); + return $this->_getSubject()->loadCache(); } /** - * Save cache - * - * @param array $tags - * @return $this + * {@inheritdoc} */ public function saveCache($tags = null) { - return $this->getSubject()->saveCache($tags); + return $this->_getSubject()->saveCache($tags); } /** - * Return Xml of node as string - * - * @return string + * {@inheritdoc} */ public function getXmlString() { - return $this->getSubject()->getXmlString(); + return $this->_getSubject()->getXmlString(); } /** - * Remove cache - * - * @return $this + * {@inheritdoc} */ public function removeCache() { - return $this->getSubject()->removeCache(); + return $this->_getSubject()->removeCache(); } /** - * Imports XML file - * - * @param string $filePath - * @return boolean + * {@inheritdoc} */ public function loadFile($filePath) { - return $this->getSubject()->loadFile($filePath); + return $this->_getSubject()->loadFile($filePath); } /** - * Imports XML string - * - * @param string $string - * @return boolean + * {@inheritdoc} */ public function loadString($string) { - return $this->getSubject()->loadString($string); + return $this->_getSubject()->loadString($string); } /** - * Imports DOM node - * - * @param \DOMNode $dom - * @return bool + * {@inheritdoc} */ public function loadDom(\DOMNode $dom) { - return $this->getSubject()->loadDom($dom); + return $this->_getSubject()->loadDom($dom); } /** - * Create node by $path and set its value. - * - * @param string $path separated by slashes - * @param string $value - * @param boolean $overwrite - * @return $this + * {@inheritdoc} */ public function setNode($path, $value, $overwrite = true) { - return $this->getSubject()->setNode($path, $value, $overwrite); + return $this->_getSubject()->setNode($path, $value, $overwrite); } /** - * Process configuration xml - * - * @return $this + * {@inheritdoc} */ public function applyExtends() { - return $this->getSubject()->applyExtends(); + return $this->_getSubject()->applyExtends(); } /** - * Stub method for processing file data right after loading the file text - * - * @param string $text - * @return string + * {@inheritdoc} */ public function processFileData($text) { - return $this->getSubject()->processFileData($text); + return $this->_getSubject()->processFileData($text); } /** - * Extend configuration - * - * @param \Magento\Framework\Simplexml\Config $config - * @param boolean $overwrite - * @return $this + * {@inheritdoc} */ public function extend(\Magento\Framework\Simplexml\Config $config, $overwrite = true) { - return $this->getSubject()->extend($config, $overwrite); + return $this->_getSubject()->extend($config, $overwrite); } } diff --git a/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php b/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php index ae986912df95d2d2a2a928056141f5b1f3b40a48..ad363e5286cba67f5b781e77d6aecf62a28f316c 100644 --- a/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php +++ b/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php @@ -8,12 +8,15 @@ namespace Magento\Framework\View\Layout\Reader; use Magento\Framework\App; use Magento\Framework\View\Layout; +/** + * Class UiComponent + */ class UiComponent implements Layout\ReaderInterface { /**#@+ * Supported types */ - const TYPE_UI_COMPONENT = 'ui_component'; + const TYPE_UI_COMPONENT = 'uiComponent'; /**#@-*/ /** @@ -39,18 +42,14 @@ class UiComponent implements Layout\ReaderInterface * @param Layout\ScheduledStructure\Helper $helper * @param string|null $scopeType */ - public function __construct( - Layout\ScheduledStructure\Helper $helper, - $scopeType = null - ) { + public function __construct(Layout\ScheduledStructure\Helper $helper, $scopeType = null) + { $this->layoutHelper = $helper; $this->scopeType = $scopeType; } /** * {@inheritdoc} - * - * @return string[] */ public function getSupportedNodes() { @@ -59,27 +58,24 @@ class UiComponent implements Layout\ReaderInterface /** * {@inheritdoc} - * - * @param Context $readerContext - * @param Layout\Element $currentElement - * @return $this */ public function interpret(Context $readerContext, Layout\Element $currentElement) { + $attributes = $this->getAttributes($currentElement); $scheduledStructure = $readerContext->getScheduledStructure(); $referenceName = $this->layoutHelper->scheduleStructure( - $readerContext->getScheduledStructure(), + $scheduledStructure, $currentElement, $currentElement->getParent(), - ['attributes' => $this->getAttributes($currentElement)] + ['attributes' => $attributes] ); - $scheduledStructure->setStructureElementData($referenceName, [ - 'attributes' => $this->getAttributes($currentElement) - ]); + + $scheduledStructure->setStructureElementData($referenceName, ['attributes' => $attributes]); $configPath = (string)$currentElement->getAttribute('ifconfig'); if (!empty($configPath)) { $scheduledStructure->setElementToIfconfigList($referenceName, $configPath, $this->scopeType); } + return $this; } @@ -95,6 +91,7 @@ class UiComponent implements Layout\ReaderInterface foreach ($this->attributes as $attributeName) { $attributes[$attributeName] = (string)$element->getAttribute($attributeName); } + return $attributes; } } diff --git a/lib/internal/Magento/Framework/View/Layout/etc/body.xsd b/lib/internal/Magento/Framework/View/Layout/etc/body.xsd index a8d5a75f795b074e2c90def67696e5a4784829b2..3b187137d61fcfbe88750b48835e516edf736d9e 100644 --- a/lib/internal/Magento/Framework/View/Layout/etc/body.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/body.xsd @@ -17,7 +17,7 @@ <xs:element ref="container" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="remove" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="move" minOccurs="0" maxOccurs="unbounded"/> - <xs:element ref="ui_component" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="uiComponent" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd index 02fe8da728aa2233fea3c1c6adbea31708de5bc2..fc44f93df682b41c5ea8182aa2d9202b8239e2df 100644 --- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd @@ -108,15 +108,15 @@ <xs:element type="containerReferenceType" name="referenceContainer"/> - <xs:element type="uiComponentType" name="ui_component"> + <xs:element type="uiComponentType" name="uiComponent"> <xs:annotation> <xs:documentation> Argument name must be unique in scope of all Blocks, Containers and other UI Components. </xs:documentation> </xs:annotation> <xs:key name="uiElementArgumentName"> - <xs:selector xpath="./arguments/argument"></xs:selector> - <xs:field xpath="@name"></xs:field> + <xs:selector xpath="./argument"/> + <xs:field xpath="@name"/> </xs:key> </xs:element> @@ -185,7 +185,7 @@ <xs:element ref="container" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="referenceBlock" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="referenceContainer" minOccurs="0" maxOccurs="unbounded"/> - <xs:element ref="ui_component" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="uiComponent" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute type="elementNameType" name="name"/> <xs:attribute type="xs:string" name="label"/> @@ -216,7 +216,7 @@ <xs:element ref="block" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="container" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="referenceBlock" minOccurs="0" maxOccurs="unbounded"/> - <xs:element ref="ui_component" minOccurs="0" /> + <xs:element ref="uiComponent" minOccurs="0" /> </xs:sequence> <xs:attribute type="elementNameType" name="name" use="optional"/> <xs:attribute type="blockClassType" name="class" use="optional"/> @@ -238,8 +238,8 @@ Part of view that can generate appropriate content. </xs:documentation> </xs:annotation> - <xs:sequence minOccurs="0" maxOccurs="unbounded"> - <xs:element ref="arguments" minOccurs="0" maxOccurs="1"/> + <xs:sequence> + <xs:element name="argument" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute type="componentNameType" name="component" use="optional"/> <xs:attribute type="elementNameType" name="name" use="optional"/> @@ -311,7 +311,7 @@ <xs:element ref="container" minOccurs="0"/> <xs:element ref="referenceBlock" minOccurs="0" /> <xs:element ref="referenceContainer" minOccurs="0"/> - <xs:element ref="ui_component" minOccurs="0" /> + <xs:element ref="uiComponent" minOccurs="0" /> </xs:choice> <xs:attribute type="elementNameType" name="name" use="required"/> </xs:complexType> @@ -322,7 +322,7 @@ <xs:element ref="block" minOccurs="0" /> <xs:element ref="container" minOccurs="0" /> <xs:element ref="referenceBlock" minOccurs="0" /> - <xs:element ref="ui_component" minOccurs="0" /> + <xs:element ref="uiComponent" minOccurs="0" /> </xs:choice> <xs:attribute type="elementNameType" name="name" use="required"/> <xs:attribute type="htmlTagType" name="htmlTag"/> diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/MessagesTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/MessagesTest.php index bd18ebe344f884734c1b78233ed278c6c8b6b440..6f552656be534c3322b7f778a769fb55c83a366c 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Element/MessagesTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/MessagesTest.php @@ -9,6 +9,7 @@ */ namespace Magento\Framework\View\Test\Unit\Element; +use Magento\Framework\Message\Manager; use \Magento\Framework\View\Element\Messages; use Magento\Framework\Message\ManagerInterface; @@ -229,7 +230,7 @@ class MessagesTest extends \PHPUnit_Framework_TestCase $this->assertEquals($emptyMessagesCacheKey, $this->messages->getCacheKeyInfo()); $messagesCacheKey = ['storage_types' => 'a:1:{i:0;s:7:"default";}']; - $this->messages->addStorageType(ManagerInterface::DEFAULT_GROUP); + $this->messages->addStorageType(Manager::DEFAULT_GROUP); $this->assertEquals($messagesCacheKey, $this->messages->getCacheKeyInfo()); } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/UiComponentTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/UiComponentTest.php index a15a926d50882d4c4fe81d5810789070a8a655cb..754a00210c34605eae25089667c656621b08d801 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/UiComponentTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/UiComponentTest.php @@ -39,6 +39,16 @@ class UiComponentTest extends \PHPUnit_Framework_TestCase */ protected $argumentInterpreterMock; + /** + * @var \Magento\Framework\View\Element\UiComponent\ContextFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextFactoryMock; + + /** + * @var \Magento\Framework\View\Element\BlockFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $blockFactoryMock; + /** * @var \Magento\Framework\View\Layout\Generator\UiComponent */ @@ -49,17 +59,31 @@ class UiComponentTest extends \PHPUnit_Framework_TestCase $this->objectManagerHelper = new ObjectManagerHelper($this); $this->argumentInterpreterMock = $this->getMockBuilder('Magento\Framework\Data\Argument\InterpreterInterface') ->disableOriginalConstructor()->getMockForAbstractClass(); - $this->uiComponentFactoryMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentFactory') ->disableOriginalConstructor()->getMock(); $this->scheduledStructureMock = $this->getMockBuilder('Magento\Framework\View\Layout\ScheduledStructure') ->disableOriginalConstructor()->getMock(); + $this->contextFactoryMock = $this->getMock( + 'Magento\Framework\View\Element\UiComponent\ContextFactory', + [], + [], + '', + false + ); + $this->blockFactoryMock = $this->getMock( + 'Magento\Framework\View\Element\BlockFactory', + [], + [], + '', + false + ); $this->uiComponent = $this->objectManagerHelper->getObject( 'Magento\Framework\View\Layout\Generator\UiComponent', [ 'uiComponentFactory' => $this->uiComponentFactoryMock, - 'argumentInterpreter' => $this->argumentInterpreterMock + 'blockFactory' => $this->blockFactoryMock, + 'contextFactory' => $this->contextFactoryMock ] ); } @@ -100,16 +124,50 @@ class UiComponentTest extends \PHPUnit_Framework_TestCase ->with($layoutMock) ->willReturnSelf(); - $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\AbstractBlock') - ->disableOriginalConstructor()->getMock(); + $componentMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponentInterface', + [], + '', + false, + true, + true, + [] + ); + + $contextMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\UiComponent\ContextInterface', + [], + '', + false + ); + $blockMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\Element\BlockInterface', + [], + '', + false + ); + + $this->contextFactoryMock->expects($this->once()) + ->method('create') + ->with( + [ + 'namespace' => 'uiComponent', + 'pageLayout' => $layoutMock + ] + )->willReturn($contextMock); $this->uiComponentFactoryMock->expects($this->any()) - ->method('createUiComponent') + ->method('create') ->with( - 'component_name', - UiComponent::TYPE, - ['attribute_1' => 'value_1', 'attribute_2' => 'value_2'] - )->willReturn($blockMock); + 'uiComponent', + null, + ['context' => $contextMock] + )->willReturn($componentMock); + + $this->blockFactoryMock->expects($this->once()) + ->method('createBlock') + ->with(UiComponent::CONTAINER, ['component' => $componentMock]) + ->willReturn($blockMock); $this->argumentInterpreterMock->expects($this->any()) ->method('evaluate') diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php index 145c8f6992e9167ec631c92fdb132f38386afac4..1c573b9a2a8915ae92c27111caaa86c10ded1f8c 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php @@ -82,8 +82,8 @@ class UiComponentTest extends \PHPUnit_Framework_TestCase return [ [ $this->getElement( - '<ui_component name="cms_block_listing" component="listing" ifconfig="config_path"/>', - 'ui_component' + '<uiComponent name="cms_block_listing" component="listing" ifconfig="config_path"/>', + 'uiComponent' ), ] ]; diff --git a/lib/internal/Magento/Framework/View/Test/Unit/LayoutTest.php b/lib/internal/Magento/Framework/View/Test/Unit/LayoutTest.php index 45effcf449e43c4e7a05dcc77d37003195069eea..3d60c5e411300fd1ba642d03ed96720959434828 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/LayoutTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/LayoutTest.php @@ -134,9 +134,6 @@ class LayoutTest extends \PHPUnit_Framework_TestCase $this->readerContextMock = $this->getMockBuilder('Magento\Framework\View\Layout\Reader\Context') ->disableOriginalConstructor() ->getMock(); - $this->readerContextFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($this->readerContextMock); $this->generatorContextFactoryMock = $this->getMockBuilder( 'Magento\Framework\View\Layout\Generator\ContextFactory' )->disableOriginalConstructor() @@ -683,6 +680,9 @@ class LayoutTest extends \PHPUnit_Framework_TestCase public function testGenerateElementsWithoutCache() { + $this->readerContextFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->readerContextMock); $layoutCacheId = 'layout_cache_id'; $handles = ['default', 'another']; /** @var \Magento\Framework\View\Layout\Element $xml */ @@ -807,4 +807,10 @@ class LayoutTest extends \PHPUnit_Framework_TestCase $this->model->generateElements(); } + + public function testGetXml() + { + $xml = '<layout/>'; + $this->assertSame($xml, \Magento\Framework\View\Layout::LAYOUT_NODE); + } } diff --git a/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php index 79cd652f4b22e85a9abc8299e6d6180f4e6037d0..1bf5137218bf4de0d49039d61593c1730a9d871c 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Webapi; use Magento\Framework\Api\AbstractExtensibleObject; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Reflection\DataObjectProcessor; +use Magento\Framework\Reflection\MethodsMap; /** * Data object converter for REST @@ -19,12 +20,21 @@ class ServiceOutputProcessor */ protected $dataObjectProcessor; + /** + * @var MethodsMap + */ + protected $methodsMapProcessor; + /** * @param DataObjectProcessor $dataObjectProcessor + * @param MethodsMap $methodsMapProcessor */ - public function __construct(DataObjectProcessor $dataObjectProcessor) - { + public function __construct( + DataObjectProcessor $dataObjectProcessor, + MethodsMap $methodsMapProcessor + ) { $this->dataObjectProcessor = $dataObjectProcessor; + $this->methodsMapProcessor = $methodsMapProcessor; } /** @@ -44,7 +54,7 @@ class ServiceOutputProcessor public function process($data, $serviceClassName, $serviceMethodName) { /** @var string $dataType */ - $dataType = $this->dataObjectProcessor->getMethodReturnType($serviceClassName, $serviceMethodName); + $dataType = $this->methodsMapProcessor->getMethodReturnType($serviceClassName, $serviceMethodName); if (is_array($data)) { $result = []; $arrayElementType = substr($dataType, 0, -2); diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json index 769a3a5d91d3f53dba9d6c08ee4fb4a25dbe4732..c2cf9161040653d1d6a8628baaee2e045fb075b3 100644 --- a/lib/internal/Magento/Framework/composer.json +++ b/lib/internal/Magento/Framework/composer.json @@ -2,7 +2,7 @@ "name": "magento/framework", "description": "N/A", "type": "magento2-library", - "version": "0.74.0-beta6", + "version": "0.74.0-beta7", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/lib/web/css/source/lib/_utilities.less b/lib/web/css/source/lib/_utilities.less index fe49f1b1cbaf9eb97148dd655ce000b4ce7ecccd..0b31aaa2f1132525036f04c4e9907ad4ca018927 100644 --- a/lib/web/css/source/lib/_utilities.less +++ b/lib/web/css/source/lib/_utilities.less @@ -467,9 +467,18 @@ appearance: @value; } +.vendor-prefix-column-count ( + @_value +) { + -webkit-column-count: @_value; + -moz-column-count: @_value; + column-count: @_value; +} + // // Pointer for popups or dropdowns // --------------------------------------------- + .pointer( @_size: 6px, @_background-color: @color-white, diff --git a/lib/web/date-format-normalizer.js b/lib/web/date-format-normalizer.js deleted file mode 100644 index f7a50afc01a7243a05da62324ecb40325e45a9d7..0000000000000000000000000000000000000000 --- a/lib/web/date-format-normalizer.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([],function(){ - 'use strict'; - - var formatCache = {}; - - function Formatter() { - - /** - * Convert from string-Magento-date-format - * to string-moment-js-date-format. Result - * stored in internal cache. - * @param {String} zendFormat - * @return {String} - */ - return function(zendFormat) { - var momentFormat = ''; - - if(formatCache[zendFormat]) { - momentFormat = formatCache[zendFormat]; - } else { - // List of differences. Got from 'MMM d, y h:mm:ss a' -> "MMM D, YYYY h:mm:ss A" - momentFormat = String(zendFormat). - replace('D','DDD'). - replace('dd','DD'). - replace('d','D'). - replace('EEEE','dddd'). - replace('EEE','ddd'). - replace('e','d'). - replace('y','YYYY'). - replace('a','A'). - toString(); - formatCache[zendFormat] = momentFormat; - } - - return momentFormat; - } - } - - return new Formatter; -}); \ No newline at end of file diff --git a/lib/web/mage/adminhtml/globals.js b/lib/web/mage/adminhtml/globals.js new file mode 100644 index 0000000000000000000000000000000000000000..c9f708bd6846e7f4366f43232148d1bccba6e5d3 --- /dev/null +++ b/lib/web/mage/adminhtml/globals.js @@ -0,0 +1,16 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ +], function () { + 'use strict'; + + /** + * Set of a temporary methods used to provide + * backward compatability with a legacy code. + */ + window.setLocation = function (url) { + window.location.href = url; + }; +}); diff --git a/lib/web/mage/utils.js b/lib/web/mage/utils.js deleted file mode 100644 index 239fca6d918ea5e78c51249e147f1a1be49e0c23..0000000000000000000000000000000000000000 --- a/lib/web/mage/utils.js +++ /dev/null @@ -1,451 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -//TODO: assemble all util methods in this module -define([ - 'underscore' -], function (_) { - 'use strict'; - - var tplRegxp = /\{(\w*)\}/g; - - /** @namespace */ - var utils = {}; - - /** - * Replaces matches of '{*}' pattern with a matched property in 'data' object. - * @private - * - * @param {String} tpl - String to process. - * @param {Object} data - Data to match with pattern. - * @returns {String} Modified string. - * - * @example - * template('Hello {one}!', {one: 'World'}); - * => 'Hello World!'; - */ - function template(tpl, data){ - return tpl.replace(tplRegxp, function(match, key){ - return data.hasOwnProperty(key) ? data[key] : ''; - }); - } - - /** - * Sets nested property of a specified object. - * @private - * - * @param {Object} parent - Object to look inside for the properties. - * @param {Array} path - Splitted path the property. - * @param {*} value - Value of the last property in 'path' array. - * returns {*} New value for the property. - */ - function setNested(parent, path, value){ - var last = path.pop(); - - path.forEach(function(part) { - if (_.isUndefined(parent[part])) { - parent[part] = {}; - } - - parent = parent[part]; - }); - - return (parent[last] = value); - } - - /** - * Retrieves value of a nested property. - * @private - * - * @param {Object} parent - Object to look inside for the properties. - * @param {Array} path - Splitted path the property. - * @returns {*} Value of the property. - */ - function getNested(parent, path){ - var exists; - - exists = path.every(function(part) { - parent = parent[part]; - - return !_.isUndefined(parent); - }); - - if(exists){ - return parent; - } - } - - /** - * Removes property from a specified object. - * @private - * - * @param {Object} parent - Object from which to remove property. - * @param {Array} path - Splitted path to the propery. - */ - function removeNested(parent, path) { - var field = path.pop(); - - parent = getNested(parent, path); - - if (_.isObject(parent)) { - delete parent[field]; - } - } - - /** - * Object manipulation methods. - */ - _.extend(utils, { - /** - * Retrieves or defines objects' property by a composite path. - * - * @param {Object} data - Container for the properties specified in path. - * @param {String} path - Objects' properties divided by dots. - * @param {*} [value] - New value for the last property. - * @returns {*} Returns value of the last property in chain. - * - * @example - * utils.nested({}, 'one.two', 3); - * => { one: {two: 3} } - */ - nested: function(data, path, value){ - var action = arguments.length > 2 ? setNested : getNested; - - path = path ? path.split('.') : []; - - return action(data, path, value); - }, - - /** - * Removes nested property from an object. - * - * @param {Object} data - Data source. - * @param {String} path - Path to the property e.g. 'one.two.three' - */ - nestedRemove: function(data, path) { - path = path.split('.'); - - removeNested(data, path); - }, - - /** - * Flattens objects' nested properties. - * - * @param {Object} data - Object to flatten. - * @param {String} [separator='.'] - Objects' keys separator. - * @returns {Object} Flattened object. - * - * @example Example with a default separator. - * utils.flatten({one: { two: { three: 'value'} }}); - * => { 'one.two.three': 'value' }; - * - * @example Example with a custom separator. - * utils.flatten({one: { two: { three: 'value'} }}, '=>'); - * => {'one=>two=>three': 'value'}; - */ - flatten: function(data, separator, parent, result){ - separator = separator || '.'; - result = result || {}; - - _.each(data, function(node, name){ - if(parent){ - name = parent + separator + name; - } - - typeof node === 'object' ? - this.flatten(node, separator, name, result) : - (result[name] = node); - - }, this); - - return result; - }, - - /** - * Opposite operation of the 'flatten' method. - * - * @param {Object} data - Previously flattened object. - * @param {String} [separator='.'] - Keys separator. - * @returns {Object} Object with nested properties. - * - * @example Example using custom separator. - * utils.unflatten({'one=>two': 'value'}, '=>'); - * => { - * one: { two: 'value' } - * }; - */ - unflatten: function(data, separator){ - var result = {}; - - separator = separator || '.'; - - _.each(data, function(value, nodes){ - nodes = nodes.split(separator); - - setNested(result, nodes, value); - }); - - return result; - }, - - /** - * Same operation as 'flatten' method, - * but returns objects' keys wrapped in '[]'. - * - * @param {Object} data - Object that should be serialized. - * @returns {Object} Serialized data. - * - * @example - * utils.serialize({one: { two: { three: 'value'} }}); - * => { 'one[two][three]': 'value' } - */ - serialize: function(data){ - var result = {}; - - data = this.flatten(data); - - _.each(data, function(value, keys){ - keys = this.serializeName(keys); - value = _.isUndefined(value) ? '' : value; - - result[keys] = value; - }, this); - - return result; - }, - - /** - * Applies provided data to the template. - * - * @param {(String|Object)} template - * @param {Object} source - Data object to match with template. - * @returns {String|Object} - * - * @example Template defined as a string. - * var source = { foo: 'Random Stuff', bar: 'Some' }; - * - * utils.template('{bar} {foo}', source); - * => 'Some Random Stuff'; - * - * @example Example of template defined as object. - * var tpl = { key: { '{bar}_Baz': '{foo}' } }; - * - * utils.template(tpl, source); - * => { key: { 'Some_Baz': 'Random Stuff' } }; - */ - template: function(templ, source){ - var result, - parse; - - if(_.isObject(templ)){ - templ = JSON.stringify(templ); - parse = true; - } - - result = template(templ, source); - - return parse ? JSON.parse(result) : result; - } - }); - - /** - * Helpers for working with strings. - */ - _.extend(utils, { - /** - * Splits string by separator if it's possible, - * otherwise returns the incoming value. - * - * @param {(String|Array|*)} str - String to split. - * @param {String} [separator=' '] - Seperator based on which to split the string. - * @returns {Array|*} Splitted string or the incoming value. - */ - stringToArray: function(str, separator){ - separator = separator || ' '; - - return typeof str === 'string' ? - str.split(separator) : - str; - }, - - /** - * Converts the incoming string which consists - * of a specified delimiters into a format commonly used in form elements. - * - * @param {String} name - The incoming string. - * @param {String} [separator='.'] - * @returns {String} Serialized string. - * - * @example - * utils.serializeName('one.two.three'); - * => 'one[two][three]'; - */ - serializeName: function(name, separator){ - var result; - - separator = separator || '.'; - name = name.split(separator); - - result = name.shift(); - - name.forEach(function(part){ - result += '[' + part + ']'; - }); - - return result; - } - }); - - /** - * Array manipulation methods. - */ - _.extend(utils, { - /** - * Facade method to remove/add value from/to array - * without creating a new instance. - * - * @param {Array} arr - Array to be modified. - * @param {*} value - Value to add/remove. - * @param {Boolean} add - Flag that specfies operation. - * @returns {Utils} Chainable. - */ - toggle: function(arr, value, add){ - return add ? - this.add(arr, value) : - this.remove(arr, value); - }, - - /** - * Removes the incoming value from array in case - * without creating a new instance of it. - * - * @param {Array} arr - Array to be modified. - * @param {*} value - Value to be removed. - * @returns {Utils} Chainable. - */ - remove: function(arr, value){ - var index = arr.indexOf(value); - - if(~index){ - arr.splice(index, 1); - } - - return this; - }, - - /** - * Adds the incoming value to array if - * it's not alredy present in there. - * - * @param {Array} arr - Array to be modifed. - * @param {...*} Values to be added. - * @returns {Utils} Chainable. - */ - add: function(arr){ - var values = _.toArray(arguments).slice(1); - - values.forEach(function(value){ - if(!~arr.indexOf(value)){ - arr.push(value); - } - }); - - return this; - }, - - /** - * Extends an incoming array with a specified ammount of undefined values - * starting from a specified position. - * - * @param {Array} container - Array to be extended. - * @param {Number} size - Ammount of values to be added. - * @param {Number} [offset=0] - Position at which to start inserting values. - * @returns {Array} Modified array. - */ - reserve: function(container, size, offset){ - container.splice(offset || 0, 0, new Array(size)); - - return _.flatten(container); - }, - - /** - * Compares multiple arrays without tracking order of their elements. - * - * @param {...Array} Multiple arrays to compare. - * @returns {Bollean} True if arrays are identical to each other. - */ - identical: function(){ - var arrays = _.toArray(arguments), - first = arrays.shift(); - - return arrays.every(function(arr) { - return ( - arr.length === first.length && - !_.difference(arr, first).length - ); - }); - } - }); - - /** - * Miscellaneous. - */ - _.extend(utils, { - /** - * Generates a unique identifier. - * - * @param {Number} [size=7] - Length of a resulting identifier. - * @returns {String} - */ - uniqueid: function (size) { - var code = (Math.random() * 25 + 65) | 0, - idstr = String.fromCharCode(code); - - size = size || 7; - - while (idstr.length < size) { - code = Math.floor((Math.random() * 42) + 48); - - if (code < 58 || code > 64) { - idstr += String.fromCharCode(code); - } - } - - return idstr; - }, - - /** - * Serializes and sends data via POST request. - * - * @param {Object} options - - * Options object that consists of - * a 'url' and 'data' properties. - */ - submit: function(options){ - var form = document.createElement('form'), - data = this.serialize(options.data), - field; - - form.setAttribute('action', options.url); - form.setAttribute('method', 'post'); - - _.each(data, function(value, name){ - field = document.createElement('input'); - - field.setAttribute('name', name); - field.setAttribute('type', 'hidden'); - - field.value = value; - - form.appendChild(field); - }); - - document.body.appendChild(form); - - form.submit(); - } - }); - - return utils; -}); \ No newline at end of file diff --git a/lib/web/mage/utils/arrays.js b/lib/web/mage/utils/arrays.js new file mode 100644 index 0000000000000000000000000000000000000000..54fb9a6189a8df0335808a989c5be5b859643ed8 --- /dev/null +++ b/lib/web/mage/utils/arrays.js @@ -0,0 +1,110 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + './strings' +], function (_, utils) { + 'use strict'; + + return { + /** + * Facade method to remove/add value from/to array + * without creating a new instance. + * + * @param {Array} arr - Array to be modified. + * @param {*} value - Value to add/remove. + * @param {Boolean} add - Flag that specfies operation. + * @returns {Utils} Chainable. + */ + toggle: function (arr, value, add) { + return add ? + this.add(arr, value) : + this.remove(arr, value); + }, + + /** + * Removes the incoming value from array in case + * without creating a new instance of it. + * + * @param {Array} arr - Array to be modified. + * @param {*} value - Value to be removed. + * @returns {Utils} Chainable. + */ + remove: function (arr, value) { + var index = arr.indexOf(value); + + if (~index) { + arr.splice(index, 1); + } + + return this; + }, + + /** + * Adds the incoming value to array if + * it's not alredy present in there. + * + * @param {Array} arr - Array to be modifed. + * @param {...*} Values to be added. + * @returns {Utils} Chainable. + */ + add: function (arr) { + var values = _.toArray(arguments).slice(1); + + values.forEach(function (value) { + if (!~arr.indexOf(value)) { + arr.push(value); + } + }); + + return this; + }, + + /** + * Extends an incoming array with a specified ammount of undefined values + * starting from a specified position. + * + * @param {Array} container - Array to be extended. + * @param {Number} size - Ammount of values to be added. + * @param {Number} [offset=0] - Position at which to start inserting values. + * @returns {Array} Modified array. + */ + reserve: function (container, size, offset) { + container.splice(offset || 0, 0, new Array(size)); + + return _.flatten(container); + }, + + /** + * Compares multiple arrays without tracking order of their elements. + * + * @param {...Array} Multiple arrays to compare. + * @returns {Bollean} True if arrays are identical to each other. + */ + identical: function () { + var arrays = _.toArray(arguments), + first = arrays.shift(); + + return arrays.every(function (arr) { + return arr.length === first.length && + !_.difference(arr, first).length; + }); + }, + + formatOffset: function(elems, offset) { + if (utils.isEmpty(offset)) { + offset = -1; + } + + offset = +offset; + + if (offset < 0) { + offset += elems.length + 1; + } + + return offset; + } + }; +}); diff --git a/lib/web/mage/utils/compare.js b/lib/web/mage/utils/compare.js new file mode 100644 index 0000000000000000000000000000000000000000..f71e1bf8922273a2d40817151ffa00599f070c7e --- /dev/null +++ b/lib/web/mage/utils/compare.js @@ -0,0 +1,133 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'mage/utils/objects' +], function (_, utils) { + 'use strict'; + + var primitives = [ + 'undefined', + 'boolean', + 'number', + 'string' + ]; + + function isDifferent(a, b) { + var oldIsPrimitive = a === null || ~primitives.indexOf(typeof a); + + return oldIsPrimitive ? a !== b : true; + } + + function fullPath(prefix, part) { + return prefix ? prefix + '.' + part : part; + } + + function format(name, newValue, oldValue, type) { + return { + name: name, + type: type, + value: newValue, + oldValue: oldValue + }; + } + + function flatten(obj, ns, result) { + result = result || {}; + ns = ns || ''; + + if (!utils.isObject(obj)) { + obj = {}; + } + + _.each(obj, function (value, key) { + key = fullPath(ns, key); + + if (utils.isObject(value)) { + flatten(value, key, result); + } + + result[key] = value; + }); + + return result; + } + + function getConatiners(changes) { + var indexed, + result = {}; + + indexed = _.indexBy(changes, 'name'); + + _.each(indexed, function (change, name) { + var path; + + name = name.split('.'); + + name.forEach(function (part) { + path = fullPath(path, part); + + if (!_.has(indexed, path)) { + result[path] = result[path] || []; + result[path].push(change); + } + }); + }); + + return result; + } + + function getModified(oldValues, current, key) { + var previous, + someIsObject; + + if (_.has(oldValues, key)) { + previous = oldValues[key]; + someIsObject = !utils.isObject(previous) || !utils.isObject(current); + + if (someIsObject && isDifferent(previous, current)) { + return format(key, current, previous, 'update'); + } + } else { + return format(key, current, undefined, 'add'); + } + } + + function getRemoved(newValues, previous, key) { + if (!_.has(newValues, key)) { + return format(key, undefined, previous, 'remove'); + } + } + + function compare(oldObj, newObj, ns) { + var removed, + modfied; + + oldObj = flatten(oldObj, ns); + newObj = flatten(newObj, ns); + + removed = _.map(oldObj, getRemoved.bind(null, newObj)), + modfied = _.map(newObj, getModified.bind(null, oldObj)); + + return _.compact(Array.prototype.concat(removed, modfied)); + } + + return { + compare: function (oldValue, newValue, ns) { + var changes = []; + + if (utils.isObject(oldValue) || utils.isObject(newValue)) { + changes = compare.apply(null, arguments); + } else if (isDifferent(oldValue, newValue)) { + changes.push(format(ns, newValue, oldValue, 'update')); + } + + return { + containers: getConatiners(changes), + changes: changes + }; + } + }; +}); diff --git a/lib/web/mage/utils/main.js b/lib/web/mage/utils/main.js new file mode 100644 index 0000000000000000000000000000000000000000..82b56e713e8c063b1f4d4920ae3d9a58bbf18478 --- /dev/null +++ b/lib/web/mage/utils/main.js @@ -0,0 +1,20 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define(function (require) { + 'use strict'; + + var utils = {}, + _ = require('underscore'); + + return _.extend( + utils, + require('./arrays'), + require('./compare'), + require('./misc'), + require('./objects'), + require('./strings'), + require('./template') + ); +}); diff --git a/lib/web/mage/utils/misc.js b/lib/web/mage/utils/misc.js new file mode 100644 index 0000000000000000000000000000000000000000..5b24831adaf97483335f910fe97e5b026d58d796 --- /dev/null +++ b/lib/web/mage/utils/misc.js @@ -0,0 +1,117 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore' +], function (_) { + 'use strict'; + + var map = { + 'D': 'DDD', + 'dd': 'DD', + 'd': 'D', + 'EEEE': 'dddd', + 'EEE': 'ddd', + 'e': 'd', + 'y': 'YYYY', + 'a': 'A' + }; + + function limitWrapper(data) { + var args = _.toArray(arguments).splice(1); + + if (data.id) { + window.clearTimeout(data.id); + } + + data.id = window.setTimeout(function () { + delete data.id; + + data.fn.apply(data.owner, args); + }, data.limit); + } + + return { + /** + * Generates a unique identifier. + * + * @param {Number} [size=7] - Length of a resulting identifier. + * @returns {String} + */ + uniqueid: function (size) { + var code = Math.random() * 25 + 65 | 0, + idstr = String.fromCharCode(code); + + size = size || 7; + + while (idstr.length < size) { + code = Math.floor(Math.random() * 42 + 48); + + if (code < 58 || code > 64) { + idstr += String.fromCharCode(code); + } + } + + return idstr; + }, + + limit: function (owner, target, limit) { + var data = { + owner: owner, + limit: limit, + fn: owner[target] + }; + + owner[target] = limitWrapper.bind(null, data); + }, + + /** + * Converts mage date format to a moment.js format. + * + * @param {String} mageFormat + * @returns {String} + */ + normalizeDate: function (mageFormat) { + var result = mageFormat; + + _.each(map, function (moment, mage) { + result = result.replace(mage, moment); + }); + + return result; + }, + + /** + * Serializes and sends data via POST request. + * + * @param {Object} options - Options object that consists of + * a 'url' and 'data' properties. + */ + submit: function (options) { + var form = document.createElement('form'), + data = this.serialize(options.data), + field; + + data.form_key = FORM_KEY; + + form.setAttribute('action', options.url); + form.setAttribute('method', 'post'); + + _.each(data, function (value, name) { + field = document.createElement('input'); + + field.setAttribute('name', name); + field.setAttribute('type', 'hidden'); + + field.value = value; + + form.appendChild(field); + }); + + document.body.appendChild(form); + + form.submit(); + } + }; +}); diff --git a/lib/web/mage/utils/objects.js b/lib/web/mage/utils/objects.js new file mode 100644 index 0000000000000000000000000000000000000000..c2d88f8386227a7779c310ff9890a11142c3c5d7 --- /dev/null +++ b/lib/web/mage/utils/objects.js @@ -0,0 +1,228 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'underscore' +], function ($, _) { + 'use strict'; + + /** + * Sets nested property of a specified object. + * @private + * + * @param {Object} parent - Object to look inside for the properties. + * @param {Array} path - Splitted path the property. + * @param {*} value - Value of the last property in 'path' array. + * returns {*} New value for the property. + */ + function setNested(parent, path, value) { + var last = path.pop(); + + path.forEach(function (part) { + if (_.isUndefined(parent[part])) { + parent[part] = {}; + } + + parent = parent[part]; + }); + + parent[last] = value; + + return value; + } + + /** + * Retrieves value of a nested property. + * @private + * + * @param {Object} parent - Object to look inside for the properties. + * @param {Array} path - Splitted path the property. + * @returns {*} Value of the property. + */ + function getNested(parent, path) { + var exists; + + exists = path.every(function (part) { + parent = parent[part]; + + return !_.isUndefined(parent); + }); + + if (exists) { + return parent; + } + } + + /** + * Removes property from a specified object. + * @private + * + * @param {Object} parent - Object from which to remove property. + * @param {Array} path - Splitted path to the propery. + */ + function removeNested(parent, path) { + var field = path.pop(); + + parent = getNested(parent, path); + + if (_.isObject(parent)) { + delete parent[field]; + } + } + + return { + /** + * Retrieves or defines objects' property by a composite path. + * + * @param {Object} data - Container for the properties specified in path. + * @param {String} path - Objects' properties divided by dots. + * @param {*} [value] - New value for the last property. + * @returns {*} Returns value of the last property in chain. + * + * @example + * utils.nested({}, 'one.two', 3); + * => { one: {two: 3} } + */ + nested: function (data, path, value) { + var action = arguments.length > 2 ? setNested : getNested; + + path = path ? path.split('.') : []; + + return action(data, path, value); + }, + + /** + * Removes nested property from an object. + * + * @param {Object} data - Data source. + * @param {String} path - Path to the property e.g. 'one.two.three' + */ + nestedRemove: function (data, path) { + path = path.split('.'); + + removeNested(data, path); + }, + + /** + * Flattens objects' nested properties. + * + * @param {Object} data - Object to flatten. + * @param {String} [separator='.'] - Objects' keys separator. + * @returns {Object} Flattened object. + * + * @example Example with a default separator. + * utils.flatten({one: { two: { three: 'value'} }}); + * => { 'one.two.three': 'value' }; + * + * @example Example with a custom separator. + * utils.flatten({one: { two: { three: 'value'} }}, '=>'); + * => {'one=>two=>three': 'value'}; + */ + flatten: function (data, separator, parent, result) { + separator = separator || '.'; + result = result || {}; + + _.each(data, function (node, name) { + if (parent) { + name = parent + separator + name; + } + + typeof node === 'object' ? + this.flatten(node, separator, name, result) : + result[name] = node; + + }, this); + + return result; + }, + + /** + * Opposite operation of the 'flatten' method. + * + * @param {Object} data - Previously flattened object. + * @param {String} [separator='.'] - Keys separator. + * @returns {Object} Object with nested properties. + * + * @example Example using custom separator. + * utils.unflatten({'one=>two': 'value'}, '=>'); + * => { + * one: { two: 'value' } + * }; + */ + unflatten: function (data, separator) { + var result = {}; + + separator = separator || '.'; + + _.each(data, function (value, nodes) { + nodes = nodes.split(separator); + + setNested(result, nodes, value); + }); + + return result; + }, + + /** + * Same operation as 'flatten' method, + * but returns objects' keys wrapped in '[]'. + * + * @param {Object} data - Object that should be serialized. + * @returns {Object} Serialized data. + * + * @example + * utils.serialize({one: { two: { three: 'value'} }}); + * => { 'one[two][three]': 'value' } + */ + serialize: function (data) { + var result = {}; + + data = this.flatten(data); + + _.each(data, function (value, keys) { + keys = this.serializeName(keys); + value = _.isUndefined(value) ? '' : value; + + result[keys] = value; + }, this); + + return result; + }, + + extend: function (target) { + var extenders = _.toArray(arguments).splice(1), + clone, + src; + + extenders.forEach(function (node) { + _.each(node, function (value, key) { + src = target[key]; + + if (this.isObject(value) || Array.isArray(value)) { + if (Array.isArray(value)) { + clone = src && Array.isArray(src) ? src : []; + } else { + clone = src && this.isObject(src) ? src : {}; + } + + target[key] = this.extend(clone, value); + } else if (!_.isUndefined(value)) { + target[key] = value; + } + }, this); + }, this); + + return target; + }, + + isObject: function (data) { + var objProto = Object.prototype; + + return typeof data == 'object' ? + objProto.toString.call(data) === '[object Object]' : + false; + } + }; +}); diff --git a/lib/web/mage/utils/strings.js b/lib/web/mage/utils/strings.js new file mode 100644 index 0000000000000000000000000000000000000000..185951886aaf3271e84cfc4d79d16016aec1d5ef --- /dev/null +++ b/lib/web/mage/utils/strings.js @@ -0,0 +1,69 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore' +], function (_) { + 'use strict'; + + return { + /** + * Splits string by separator if it's possible, + * otherwise returns the incoming value. + * + * @param {(String|Array|*)} str - String to split. + * @param {String} [separator=' '] - Seperator based on which to split the string. + * @returns {Array|*} Splitted string or the incoming value. + */ + stringToArray: function (str, separator) { + separator = separator || ' '; + + return typeof str === 'string' ? + str.split(separator) : + str; + }, + + /** + * Converts the incoming string which consists + * of a specified delimiters into a format commonly used in form elements. + * + * @param {String} name - The incoming string. + * @param {String} [separator='.'] + * @returns {String} Serialized string. + * + * @example + * utils.serializeName('one.two.three'); + * => 'one[two][three]'; + */ + serializeName: function (name, separator) { + var result; + + separator = separator || '.'; + name = name.split(separator); + + result = name.shift(); + + name.forEach(function (part) { + result += '[' + part + ']'; + }); + + return result; + }, + + /** + * Checks wether the incoming value is not empty, + * e.g. not 'null' or 'undefined' + * + * @param {*} value - Value to check. + * @returns {Boolean} + */ + isEmpty: function (value) { + return value === '' || _.isUndefined(value) || _.isNull(value); + }, + + fullPath: function (prefix, part) { + return prefix ? prefix + '.' + part : part; + } + }; +}); diff --git a/lib/web/mage/utils/template.js b/lib/web/mage/utils/template.js new file mode 100644 index 0000000000000000000000000000000000000000..86c53247dcf9776400136e09e5e56f434c50481e --- /dev/null +++ b/lib/web/mage/utils/template.js @@ -0,0 +1,84 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'mage/utils/objects' +], function (_, utils) { + 'use strict'; + + var opener = '<%'; + + function isTemplate(value) { + return _.isString(value) && ~value.indexOf(opener); + } + + function render(tmpl, data) { + var last = tmpl; + + data = Object.create(data); + + while (~tmpl.indexOf(opener)) { + tmpl = _.template(tmpl)(data); + + if (tmpl === last) { + break; + } + + last = tmpl; + } + + return tmpl; + } + + return { + /** + * Applies provided data to the template. + * + * @param {Object} tmpl + * @param {Object} [$data] - Data object to match with template. + * @returns {Object} + * + * @example Template defined as a string. + * var source = { foo: 'Random Stuff', bar: 'Some' }; + * + * utils.template('{bar} {foo}', source); + * => 'Some Random Stuff'; + * + * @example Example of template defined as object. + * var tpl = { key: { '{bar}_Baz': '{foo}' } }; + * + * utils.template(tpl, source); + * => { key: { 'Some_Baz': 'Random Stuff' } }; + */ + template: function (tmpl, $data) { + tmpl = utils.extend({}, tmpl); + + tmpl.$data = $data || {}; + + _.each(tmpl, function iterate(value, key, list) { + if (key === '$data') { + return; + } + + if (isTemplate(key)) { + delete list[key]; + + key = render(key, tmpl); + list[key] = value; + } + + if (isTemplate(value)) { + list[key] = render(value, tmpl); + } else if (_.isObject(value)) { + _.each(value, iterate); + } + }); + + delete tmpl.$data; + + return tmpl; + } + }; +}); diff --git a/lib/web/underscore.js b/lib/web/underscore.js index d5b3375f28d445b12ae8bdc7bbcebb8031ed48a2..e272fca43f7b6c59357fcf20d791e2295e44921f 100644 --- a/lib/web/underscore.js +++ b/lib/web/underscore.js @@ -1,6 +1,6 @@ -// Underscore.js 1.7.0 +// Underscore.js 1.8.2 // http://underscorejs.org -// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // Underscore may be freely distributed under the MIT license. (function() { @@ -21,7 +21,6 @@ var push = ArrayProto.push, slice = ArrayProto.slice, - concat = ArrayProto.concat, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; @@ -30,7 +29,11 @@ var nativeIsArray = Array.isArray, nativeKeys = Object.keys, - nativeBind = FuncProto.bind; + nativeBind = FuncProto.bind, + nativeCreate = Object.create; + + // Naked function reference for surrogate-prototype-swapping. + var Ctor = function(){}; // Create a safe reference to the Underscore object for use below. var _ = function(obj) { @@ -52,12 +55,12 @@ } // Current version. - _.VERSION = '1.7.0'; + _.VERSION = '1.8.2'; // Internal function that returns an efficient (for current engines) version // of the passed-in callback, to be repeatedly applied in other Underscore // functions. - var createCallback = function(func, context, argCount) { + var optimizeCb = function(func, context, argCount) { if (context === void 0) return func; switch (argCount == null ? 3 : argCount) { case 1: return function(value) { @@ -81,12 +84,52 @@ // A mostly-internal function to generate callbacks that can be applied // to each element in a collection, returning the desired result — either // identity, an arbitrary callback, a property matcher, or a property accessor. - _.iteratee = function(value, context, argCount) { + var cb = function(value, context, argCount) { if (value == null) return _.identity; - if (_.isFunction(value)) return createCallback(value, context, argCount); - if (_.isObject(value)) return _.matches(value); + if (_.isFunction(value)) return optimizeCb(value, context, argCount); + if (_.isObject(value)) return _.matcher(value); return _.property(value); }; + _.iteratee = function(value, context) { + return cb(value, context, Infinity); + }; + + // An internal function for creating assigner functions. + var createAssigner = function(keysFunc, undefinedOnly) { + return function(obj) { + var length = arguments.length; + if (length < 2 || obj == null) return obj; + for (var index = 1; index < length; index++) { + var source = arguments[index], + keys = keysFunc(source), + l = keys.length; + for (var i = 0; i < l; i++) { + var key = keys[i]; + if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; + } + } + return obj; + }; + }; + + // An internal function for creating a new object that inherits from another. + var baseCreate = function(prototype) { + if (!_.isObject(prototype)) return {}; + if (nativeCreate) return nativeCreate(prototype); + Ctor.prototype = prototype; + var result = new Ctor; + Ctor.prototype = null; + return result; + }; + + // Helper for collection methods to determine whether a collection + // should be iterated as an array or as an object + // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; + var isArrayLike = function(collection) { + var length = collection && collection.length; + return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; + }; // Collection Functions // -------------------- @@ -95,11 +138,10 @@ // Handles raw objects in addition to array-likes. Treats all // sparse array-likes as if they were dense. _.each = _.forEach = function(obj, iteratee, context) { - if (obj == null) return obj; - iteratee = createCallback(iteratee, context); - var i, length = obj.length; - if (length === +length) { - for (i = 0; i < length; i++) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj); } } else { @@ -113,77 +155,66 @@ // Return the results of applying the iteratee to each element. _.map = _.collect = function(obj, iteratee, context) { - if (obj == null) return []; - iteratee = _.iteratee(iteratee, context); - var keys = obj.length !== +obj.length && _.keys(obj), + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length, - results = Array(length), - currentKey; + results = Array(length); for (var index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; + var currentKey = keys ? keys[index] : index; results[index] = iteratee(obj[currentKey], currentKey, obj); } return results; }; - var reduceError = 'Reduce of empty array with no initial value'; + // Create a reducing function iterating left or right. + function createReduce(dir) { + // Optimized iterator function as using arguments.length + // in the main function will deoptimize the, see #1991. + function iterator(obj, iteratee, memo, keys, index, length) { + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + } + + return function(obj, iteratee, memo, context) { + iteratee = optimizeCb(iteratee, context, 4); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + // Determine the initial value if none is provided. + if (arguments.length < 3) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + return iterator(obj, iteratee, memo, keys, index, length); + }; + } // **Reduce** builds up a single result from a list of values, aka `inject`, // or `foldl`. - _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) { - if (obj == null) obj = []; - iteratee = createCallback(iteratee, context, 4); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index = 0, currentKey; - if (arguments.length < 3) { - if (!length) throw new TypeError(reduceError); - memo = obj[keys ? keys[index++] : index++]; - } - for (; index < length; index++) { - currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; + _.reduce = _.foldl = _.inject = createReduce(1); // The right-associative version of reduce, also known as `foldr`. - _.reduceRight = _.foldr = function(obj, iteratee, memo, context) { - if (obj == null) obj = []; - iteratee = createCallback(iteratee, context, 4); - var keys = obj.length !== + obj.length && _.keys(obj), - index = (keys || obj).length, - currentKey; - if (arguments.length < 3) { - if (!index) throw new TypeError(reduceError); - memo = obj[keys ? keys[--index] : --index]; - } - while (index--) { - currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; + _.reduceRight = _.foldr = createReduce(-1); // Return the first value which passes a truth test. Aliased as `detect`. _.find = _.detect = function(obj, predicate, context) { - var result; - predicate = _.iteratee(predicate, context); - _.some(obj, function(value, index, list) { - if (predicate(value, index, list)) { - result = value; - return true; - } - }); - return result; + var key; + if (isArrayLike(obj)) { + key = _.findIndex(obj, predicate, context); + } else { + key = _.findKey(obj, predicate, context); + } + if (key !== void 0 && key !== -1) return obj[key]; }; // Return all the elements that pass a truth test. // Aliased as `select`. _.filter = _.select = function(obj, predicate, context) { var results = []; - if (obj == null) return results; - predicate = _.iteratee(predicate, context); + predicate = cb(predicate, context); _.each(obj, function(value, index, list) { if (predicate(value, index, list)) results.push(value); }); @@ -192,19 +223,17 @@ // Return all the elements for which a truth test fails. _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(_.iteratee(predicate)), context); + return _.filter(obj, _.negate(cb(predicate)), context); }; // Determine whether all of the elements match a truth test. // Aliased as `all`. _.every = _.all = function(obj, predicate, context) { - if (obj == null) return true; - predicate = _.iteratee(predicate, context); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index, currentKey; - for (index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; if (!predicate(obj[currentKey], currentKey, obj)) return false; } return true; @@ -213,24 +242,21 @@ // Determine if at least one element in the object matches a truth test. // Aliased as `any`. _.some = _.any = function(obj, predicate, context) { - if (obj == null) return false; - predicate = _.iteratee(predicate, context); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index, currentKey; - for (index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; if (predicate(obj[currentKey], currentKey, obj)) return true; } return false; }; // Determine if the array or object contains a given value (using `===`). - // Aliased as `include`. - _.contains = _.include = function(obj, target) { - if (obj == null) return false; - if (obj.length !== +obj.length) obj = _.values(obj); - return _.indexOf(obj, target) >= 0; + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function(obj, target, fromIndex) { + if (!isArrayLike(obj)) obj = _.values(obj); + return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0; }; // Invoke a method (with arguments) on every item in a collection. @@ -238,7 +264,8 @@ var args = slice.call(arguments, 2); var isFunc = _.isFunction(method); return _.map(obj, function(value) { - return (isFunc ? method : value[method]).apply(value, args); + var func = isFunc ? method : value[method]; + return func == null ? func : func.apply(value, args); }); }; @@ -250,13 +277,13 @@ // Convenience version of a common use case of `filter`: selecting only objects // containing specific `key:value` pairs. _.where = function(obj, attrs) { - return _.filter(obj, _.matches(attrs)); + return _.filter(obj, _.matcher(attrs)); }; // Convenience version of a common use case of `find`: getting the first object // containing specific `key:value` pairs. _.findWhere = function(obj, attrs) { - return _.find(obj, _.matches(attrs)); + return _.find(obj, _.matcher(attrs)); }; // Return the maximum element (or element-based computation). @@ -264,7 +291,7 @@ var result = -Infinity, lastComputed = -Infinity, value, computed; if (iteratee == null && obj != null) { - obj = obj.length === +obj.length ? obj : _.values(obj); + obj = isArrayLike(obj) ? obj : _.values(obj); for (var i = 0, length = obj.length; i < length; i++) { value = obj[i]; if (value > result) { @@ -272,7 +299,7 @@ } } } else { - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); _.each(obj, function(value, index, list) { computed = iteratee(value, index, list); if (computed > lastComputed || computed === -Infinity && result === -Infinity) { @@ -289,7 +316,7 @@ var result = Infinity, lastComputed = Infinity, value, computed; if (iteratee == null && obj != null) { - obj = obj.length === +obj.length ? obj : _.values(obj); + obj = isArrayLike(obj) ? obj : _.values(obj); for (var i = 0, length = obj.length; i < length; i++) { value = obj[i]; if (value < result) { @@ -297,7 +324,7 @@ } } } else { - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); _.each(obj, function(value, index, list) { computed = iteratee(value, index, list); if (computed < lastComputed || computed === Infinity && result === Infinity) { @@ -312,7 +339,7 @@ // Shuffle a collection, using the modern version of the // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). _.shuffle = function(obj) { - var set = obj && obj.length === +obj.length ? obj : _.values(obj); + var set = isArrayLike(obj) ? obj : _.values(obj); var length = set.length; var shuffled = Array(length); for (var index = 0, rand; index < length; index++) { @@ -328,7 +355,7 @@ // The internal `guard` argument allows it to work with `map`. _.sample = function(obj, n, guard) { if (n == null || guard) { - if (obj.length !== +obj.length) obj = _.values(obj); + if (!isArrayLike(obj)) obj = _.values(obj); return obj[_.random(obj.length - 1)]; } return _.shuffle(obj).slice(0, Math.max(0, n)); @@ -336,7 +363,7 @@ // Sort the object's values by a criterion produced by an iteratee. _.sortBy = function(obj, iteratee, context) { - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); return _.pluck(_.map(obj, function(value, index, list) { return { value: value, @@ -358,7 +385,7 @@ var group = function(behavior) { return function(obj, iteratee, context) { var result = {}; - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); _.each(obj, function(value, index) { var key = iteratee(value, index, obj); behavior(result, value, key); @@ -386,37 +413,24 @@ if (_.has(result, key)) result[key]++; else result[key] = 1; }); - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = _.iteratee(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = array.length; - while (low < high) { - var mid = low + high >>> 1; - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - // Safely create a real, live array from anything iterable. _.toArray = function(obj) { if (!obj) return []; if (_.isArray(obj)) return slice.call(obj); - if (obj.length === +obj.length) return _.map(obj, _.identity); + if (isArrayLike(obj)) return _.map(obj, _.identity); return _.values(obj); }; // Return the number of elements in an object. _.size = function(obj) { if (obj == null) return 0; - return obj.length === +obj.length ? obj.length : _.keys(obj).length; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; }; // Split a collection into two arrays: one whose elements all satisfy the given // predicate, and one whose elements all do not satisfy the predicate. _.partition = function(obj, predicate, context) { - predicate = _.iteratee(predicate, context); + predicate = cb(predicate, context); var pass = [], fail = []; _.each(obj, function(value, key, obj) { (predicate(value, key, obj) ? pass : fail).push(value); @@ -433,30 +447,27 @@ _.first = _.head = _.take = function(array, n, guard) { if (array == null) return void 0; if (n == null || guard) return array[0]; - if (n < 0) return []; - return slice.call(array, 0, n); + return _.initial(array, array.length - n); }; // Returns everything but the last entry of the array. Especially useful on // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. The **guard** check allows it to work with - // `_.map`. + // the array, excluding the last N. _.initial = function(array, n, guard) { return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); }; // Get the last element of an array. Passing **n** will return the last N - // values in the array. The **guard** check allows it to work with `_.map`. + // values in the array. _.last = function(array, n, guard) { if (array == null) return void 0; if (n == null || guard) return array[array.length - 1]; - return slice.call(array, Math.max(array.length - n, 0)); + return _.rest(array, Math.max(0, array.length - n)); }; // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. The **guard** - // check allows it to work with `_.map`. + // the rest N values in the array. _.rest = _.tail = _.drop = function(array, n, guard) { return slice.call(array, n == null || guard ? 1 : n); }; @@ -467,18 +478,20 @@ }; // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, strict, output) { - if (shallow && _.every(input, _.isArray)) { - return concat.apply(output, input); - } - for (var i = 0, length = input.length; i < length; i++) { + var flatten = function(input, shallow, strict, startIndex) { + var output = [], idx = 0; + for (var i = startIndex || 0, length = input && input.length; i < length; i++) { var value = input[i]; - if (!_.isArray(value) && !_.isArguments(value)) { - if (!strict) output.push(value); - } else if (shallow) { - push.apply(output, value); - } else { - flatten(value, shallow, strict, output); + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + //flatten current level of array or arguments object + if (!shallow) value = flatten(value, shallow, strict); + var j = 0, len = value.length; + output.length += len; + while (j < len) { + output[idx++] = value[j++]; + } + } else if (!strict) { + output[idx++] = value; } } return output; @@ -486,7 +499,7 @@ // Flatten out an array, either recursively (by default), or just one level. _.flatten = function(array, shallow) { - return flatten(array, shallow, false, []); + return flatten(array, shallow, false); }; // Return a version of the array that does not contain the specified value(s). @@ -504,21 +517,21 @@ iteratee = isSorted; isSorted = false; } - if (iteratee != null) iteratee = _.iteratee(iteratee, context); + if (iteratee != null) iteratee = cb(iteratee, context); var result = []; var seen = []; for (var i = 0, length = array.length; i < length; i++) { - var value = array[i]; + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; if (isSorted) { - if (!i || seen !== value) result.push(value); - seen = value; + if (!i || seen !== computed) result.push(value); + seen = computed; } else if (iteratee) { - var computed = iteratee(value, i, array); - if (_.indexOf(seen, computed) < 0) { + if (!_.contains(seen, computed)) { seen.push(computed); result.push(value); } - } else if (_.indexOf(result, value) < 0) { + } else if (!_.contains(result, value)) { result.push(value); } } @@ -528,7 +541,7 @@ // Produce an array that contains the union: each distinct element from all of // the passed-in arrays. _.union = function() { - return _.uniq(flatten(arguments, true, true, [])); + return _.uniq(flatten(arguments, true, true)); }; // Produce an array that contains every item shared between all the @@ -551,7 +564,7 @@ // Take the difference between one array and a number of other arrays. // Only the elements present in just the first array will remain. _.difference = function(array) { - var rest = flatten(slice.call(arguments, 1), true, true, []); + var rest = flatten(arguments, true, true, 1); return _.filter(array, function(value){ return !_.contains(rest, value); }); @@ -559,23 +572,28 @@ // Zip together multiple lists into a single array -- elements that share // an index go together. - _.zip = function(array) { - if (array == null) return []; - var length = _.max(arguments, 'length').length; - var results = Array(length); - for (var i = 0; i < length; i++) { - results[i] = _.pluck(arguments, i); + _.zip = function() { + return _.unzip(arguments); + }; + + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices + _.unzip = function(array) { + var length = array && _.max(array, 'length').length || 0; + var result = Array(length); + + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); } - return results; + return result; }; // Converts lists into objects. Pass either a single array of `[key, value]` // pairs, or two parallel arrays of the same length -- one of keys, and one of // the corresponding values. _.object = function(list, values) { - if (list == null) return {}; var result = {}; - for (var i = 0, length = list.length; i < length; i++) { + for (var i = 0, length = list && list.length; i < length; i++) { if (values) { result[list[i]] = values[i]; } else { @@ -590,30 +608,63 @@ // If the array is large and already in sort order, pass `true` // for **isSorted** to use binary search. _.indexOf = function(array, item, isSorted) { - if (array == null) return -1; - var i = 0, length = array.length; - if (isSorted) { - if (typeof isSorted == 'number') { - i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted; - } else { - i = _.sortedIndex(array, item); - return array[i] === item ? i : -1; - } + var i = 0, length = array && array.length; + if (typeof isSorted == 'number') { + i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted; + } else if (isSorted && length) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (item !== item) { + return _.findIndex(slice.call(array, i), _.isNaN); } for (; i < length; i++) if (array[i] === item) return i; return -1; }; _.lastIndexOf = function(array, item, from) { - if (array == null) return -1; - var idx = array.length; + var idx = array ? array.length : 0; if (typeof from == 'number') { idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1); } + if (item !== item) { + return _.findLastIndex(slice.call(array, 0, idx), _.isNaN); + } while (--idx >= 0) if (array[idx] === item) return idx; return -1; }; + // Generator function to create the findIndex and findLastIndex functions + function createIndexFinder(dir) { + return function(array, predicate, context) { + predicate = cb(predicate, context); + var length = array != null && array.length; + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + } + + // Returns the first index on an array-like that passes a predicate test + _.findIndex = createIndexFinder(1); + + _.findLastIndex = createIndexFinder(-1); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = array.length; + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + // Generate an integer Array containing an arithmetic progression. A port of // the native Python `range()` function. See // [the Python documentation](http://docs.python.org/library/functions.html#range). @@ -637,25 +688,25 @@ // Function (ahem) Functions // ------------------ - // Reusable constructor function for prototype setting. - var Ctor = function(){}; + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments + var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; // Create a function bound to a given object (assigning `this`, and arguments, // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if // available. _.bind = function(func, context) { - var args, bound; if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); - args = slice.call(arguments, 2); - bound = function() { - if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); - Ctor.prototype = func.prototype; - var self = new Ctor; - Ctor.prototype = null; - var result = func.apply(self, args.concat(slice.call(arguments))); - if (_.isObject(result)) return result; - return self; + var args = slice.call(arguments, 2); + var bound = function() { + return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); }; return bound; }; @@ -665,15 +716,16 @@ // as a placeholder, allowing any combination of arguments to be pre-filled. _.partial = function(func) { var boundArgs = slice.call(arguments, 1); - return function() { - var position = 0; - var args = boundArgs.slice(); - for (var i = 0, length = args.length; i < length; i++) { - if (args[i] === _) args[i] = arguments[position++]; + var bound = function() { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; } while (position < arguments.length) args.push(arguments[position++]); - return func.apply(this, args); + return executeBound(func, bound, this, this, args); }; + return bound; }; // Bind a number of an object's methods to that object. Remaining arguments @@ -693,7 +745,7 @@ _.memoize = function(func, hasher) { var memoize = function(key) { var cache = memoize.cache; - var address = hasher ? hasher.apply(this, arguments) : key; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); return cache[address]; }; @@ -712,9 +764,7 @@ // Defers a function, scheduling it to run after the current call stack has // cleared. - _.defer = function(func) { - return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); - }; + _.defer = _.partial(_.delay, _, 1); // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. Normally, the throttled function will run @@ -739,8 +789,10 @@ context = this; args = arguments; if (remaining <= 0 || remaining > wait) { - clearTimeout(timeout); - timeout = null; + if (timeout) { + clearTimeout(timeout); + timeout = null; + } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; @@ -761,7 +813,7 @@ var later = function() { var last = _.now() - timestamp; - if (last < wait && last > 0) { + if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); } else { timeout = null; @@ -814,7 +866,7 @@ }; }; - // Returns a function that will only be executed after being called N times. + // Returns a function that will only be executed on and after the Nth call. _.after = function(times, func) { return function() { if (--times < 1) { @@ -823,15 +875,14 @@ }; }; - // Returns a function that will only be executed before being called N times. + // Returns a function that will only be executed up to (but not including) the Nth call. _.before = function(times, func) { var memo; return function() { if (--times > 0) { memo = func.apply(this, arguments); - } else { - func = null; } + if (times <= 1) func = null; return memo; }; }; @@ -843,13 +894,47 @@ // Object Functions // ---------------- - // Retrieve the names of an object's properties. + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; + + function collectNonEnumProps(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; + + // Constructor is a special case. + var prop = 'constructor'; + if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); + + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + } + + // Retrieve the names of an object's own properties. // Delegates to **ECMAScript 5**'s native `Object.keys` _.keys = function(obj) { if (!_.isObject(obj)) return []; if (nativeKeys) return nativeKeys(obj); var keys = []; for (var key in obj) if (_.has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve all the property names of an object. + _.allKeys = function(obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); return keys; }; @@ -864,6 +949,21 @@ return values; }; + // Returns the results of applying the iteratee to each element of the object + // In contrast to _.map it returns an object + _.mapObject = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}, + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + // Convert an object into a list of `[key, value]` pairs. _.pairs = function(obj) { var keys = _.keys(obj); @@ -896,37 +996,38 @@ }; // Extend a given object with all the properties in passed-in object(s). - _.extend = function(obj) { - if (!_.isObject(obj)) return obj; - var source, prop; - for (var i = 1, length = arguments.length; i < length; i++) { - source = arguments[i]; - for (prop in source) { - if (hasOwnProperty.call(source, prop)) { - obj[prop] = source[prop]; - } - } + _.extend = createAssigner(_.allKeys); + + // Assigns a given object with all the own properties in the passed-in object(s) + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); + + // Returns the first key on an object that passes a predicate test + _.findKey = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; } - return obj; }; // Return a copy of the object only containing the whitelisted properties. - _.pick = function(obj, iteratee, context) { - var result = {}, key; + _.pick = function(object, oiteratee, context) { + var result = {}, obj = object, iteratee, keys; if (obj == null) return result; - if (_.isFunction(iteratee)) { - iteratee = createCallback(iteratee, context); - for (key in obj) { - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } + if (_.isFunction(oiteratee)) { + keys = _.allKeys(obj); + iteratee = optimizeCb(oiteratee, context); } else { - var keys = concat.apply([], slice.call(arguments, 1)); - obj = new Object(obj); - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (key in obj) result[key] = obj[key]; - } + keys = flatten(arguments, false, false, 1); + iteratee = function(value, key, obj) { return key in obj; }; + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; } return result; }; @@ -936,7 +1037,7 @@ if (_.isFunction(iteratee)) { iteratee = _.negate(iteratee); } else { - var keys = _.map(concat.apply([], slice.call(arguments, 1)), String); + var keys = _.map(flatten(arguments, false, false, 1), String); iteratee = function(value, key) { return !_.contains(keys, key); }; @@ -945,16 +1046,7 @@ }; // Fill in a given object with default properties. - _.defaults = function(obj) { - if (!_.isObject(obj)) return obj; - for (var i = 1, length = arguments.length; i < length; i++) { - var source = arguments[i]; - for (var prop in source) { - if (obj[prop] === void 0) obj[prop] = source[prop]; - } - } - return obj; - }; + _.defaults = createAssigner(_.allKeys, true); // Create a (shallow-cloned) duplicate of an object. _.clone = function(obj) { @@ -970,6 +1062,19 @@ return obj; }; + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function(object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + + // Internal recursive comparison function for `isEqual`. var eq = function(a, b, aStack, bStack) { // Identical objects are equal. `0 === -0`, but they aren't identical. @@ -1004,74 +1109,76 @@ // of `NaN` are not equivalent. return +a === +b; } - if (typeof a != 'object' || typeof b != 'object') return false; + + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; + + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } // Assume equality for cyclic structures. The algorithm for detecting cyclic // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; var length = aStack.length; while (length--) { // Linear search. Performance is inversely proportional to the number of // unique nested structures. if (aStack[length] === a) return bStack[length] === b; } - // Objects with different constructors are not equivalent, but `Object`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if ( - aCtor !== bCtor && - // Handle Object.create(x) cases - 'constructor' in a && 'constructor' in b && - !(_.isFunction(aCtor) && aCtor instanceof aCtor && - _.isFunction(bCtor) && bCtor instanceof bCtor) - ) { - return false; - } + // Add the first object to the stack of traversed objects. aStack.push(a); bStack.push(b); - var size, result; + // Recursively compare objects and arrays. - if (className === '[object Array]') { + if (areArrays) { // Compare array lengths to determine if a deep comparison is necessary. - size = a.length; - result = size === b.length; - if (result) { - // Deep compare the contents, ignoring non-numeric properties. - while (size--) { - if (!(result = eq(a[size], b[size], aStack, bStack))) break; - } + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; } } else { // Deep compare objects. var keys = _.keys(a), key; - size = keys.length; + length = keys.length; // Ensure that both objects contain the same number of properties before comparing deep equality. - result = _.keys(b).length === size; - if (result) { - while (size--) { - // Deep compare each member - key = keys[size]; - if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; - } + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; } } // Remove the first object from the stack of traversed objects. aStack.pop(); bStack.pop(); - return result; + return true; }; // Perform a deep comparison to check if two objects are equal. _.isEqual = function(a, b) { - return eq(a, b, [], []); + return eq(a, b); }; // Is a given array, string, or object empty? // An "empty" object has no enumerable own-properties. _.isEmpty = function(obj) { if (obj == null) return true; - if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0; - for (var key in obj) if (_.has(obj, key)) return false; - return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; }; // Is a given value a DOM element? @@ -1091,14 +1198,14 @@ return type === 'function' || type === 'object' && !!obj; }; - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. - _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { _['is' + name] = function(obj) { return toString.call(obj) === '[object ' + name + ']'; }; }); - // Define a fallback version of the method in browsers (ahem, IE), where + // Define a fallback version of the method in browsers (ahem, IE < 9), where // there isn't any inspectable "Arguments" type. if (!_.isArguments(arguments)) { _.isArguments = function(obj) { @@ -1106,8 +1213,9 @@ }; } - // Optimize `isFunction` if appropriate. Work around an IE 11 bug. - if (typeof /./ !== 'function') { + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), and in Safari 8 (#1929). + if (typeof /./ != 'function' && typeof Int8Array != 'object') { _.isFunction = function(obj) { return typeof obj == 'function' || false; }; @@ -1170,28 +1278,30 @@ _.property = function(key) { return function(obj) { + return obj == null ? void 0 : obj[key]; + }; + }; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function(obj) { + return obj == null ? function(){} : function(key) { return obj[key]; }; }; - // Returns a predicate for checking whether an object has a given set of `key:value` pairs. - _.matches = function(attrs) { - var pairs = _.pairs(attrs), length = pairs.length; + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function(attrs) { + attrs = _.extendOwn({}, attrs); return function(obj) { - if (obj == null) return !length; - obj = new Object(obj); - for (var i = 0; i < length; i++) { - var pair = pairs[i], key = pair[0]; - if (pair[1] !== obj[key] || !(key in obj)) return false; - } - return true; + return _.isMatch(obj, attrs); }; }; // Run a function **n** times. _.times = function(n, iteratee, context) { var accum = Array(Math.max(0, n)); - iteratee = createCallback(iteratee, context, 1); + iteratee = optimizeCb(iteratee, context, 1); for (var i = 0; i < n; i++) accum[i] = iteratee(i); return accum; }; @@ -1240,10 +1350,12 @@ // If the value of the named `property` is a function then invoke it with the // `object` as context; otherwise, return it. - _.result = function(object, property) { - if (object == null) return void 0; - var value = object[property]; - return _.isFunction(value) ? object[property]() : value; + _.result = function(object, property, fallback) { + var value = object == null ? void 0 : object[property]; + if (value === void 0) { + value = fallback; + } + return _.isFunction(value) ? value.call(object) : value; }; // Generate a unique integer id (unique within the entire client session). @@ -1358,8 +1470,8 @@ // underscore functions. Wrapped objects may be chained. // Helper function to continue chaining intermediate results. - var result = function(obj) { - return this._chain ? _(obj).chain() : obj; + var result = function(instance, obj) { + return instance._chain ? _(obj).chain() : obj; }; // Add your own custom functions to the Underscore object. @@ -1369,7 +1481,7 @@ _.prototype[name] = function() { var args = [this._wrapped]; push.apply(args, arguments); - return result.call(this, func.apply(_, args)); + return result(this, func.apply(_, args)); }; }); }; @@ -1384,7 +1496,7 @@ var obj = this._wrapped; method.apply(obj, arguments); if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; - return result.call(this, obj); + return result(this, obj); }; }); @@ -1392,7 +1504,7 @@ _.each(['concat', 'join', 'slice'], function(name) { var method = ArrayProto[name]; _.prototype[name] = function() { - return result.call(this, method.apply(this._wrapped, arguments)); + return result(this, method.apply(this._wrapped, arguments)); }; }); @@ -1401,6 +1513,14 @@ return this._wrapped; }; + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function() { + return '' + this._wrapped; + }; + // AMD registration happens at the end for compatibility with AMD loaders // that may not enforce next-turn semantics on modules. Even though general // practice for AMD registration is to be anonymous, underscore registers diff --git a/package.json b/package.json index eaee4e18e2484b09731ec9a8e2a165eef83ae29c..69657eb7702c63f3d94d50a5d2f613ae6643f33e 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "grunt-contrib-watch": "^0.6.1", "grunt-exec": "^0.4.6", "grunt-styledocco": "^0.1.4", - "grunt-template-jasmine-requirejs": "^0.2.0", + "grunt-template-jasmine-requirejs": "^0.2.3", "grunt-text-replace": "^0.4.0", "imagemin-svgo": "^4.0.1", "load-grunt-config": "^0.16.0", diff --git a/setup/performance-toolkit/README.txt b/setup/performance-toolkit/README.txt index fda8a78c11c5827b18ccb364bd39f78b41ed58d3..f290b25553df3596233e5c767e0d1bb7f7fd2d1d 100644 --- a/setup/performance-toolkit/README.txt +++ b/setup/performance-toolkit/README.txt @@ -32,8 +32,8 @@ Scenario can accept parameters that are described bellow in format <parameter_na <customer_checkout_percent:4/> Percentage of users that will reach the (logged-in) customer checkout stage. Default is '4'. <loops:1/> Number of loops to run. Default is '1'. <admin_path:admin/> Admin backend path. Default is 'admin'. -<admin_user:admin/> Admin backend user. Default is 'admin'. -<admin_password:123123q/> Admin backend password. Default is '123123q'. +<admin-user:admin/> Admin backend user. Default is 'admin'. +<admin-password:123123q/> Admin backend password. Default is '123123q'. <think_time_deviation:1000> Deviation (ms) for "think time" emulation. Default is '1000'. <think_time_delay_offset:2000> Constant delay offset (ms) for "think time" emulation. Default is '2000'. @@ -85,22 +85,3 @@ Details http://jmeter.apache.org/usermanual/component_reference.html#View_Result About other types read on http://jmeter.apache.org/usermanual/component_reference.html - - -Testing environment ------------ - -jMeter: apache-jmeter-2.11 -OS (where jMeter is running): Windows 7 SP1 -Server (where Magento is hosted): Intel(R) Core(TM)2 Duo CPU T7700 @2.40GHz, memtotal 4gb. -PHP: 5.4.19 (memory_limit 2Gb) -MySQL: 5.5.29 MySQL Community Server -Magento version: ver. 2.0.0.0-dev70 (rev 16b68a0f8e0fad4375f33b7238e2f2964ac3aadc) -Magento database (Small plan in Fixture Generation Tool): -jMeter parameters (all default parameters): - users: 100 - ramp_period: 300 - view_product_add_to_cart_percent: 62 - view_catalog_percent: 30 - guest_checkout_percent: 4 - customer_checkout_percent: 4 diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 7d3d7aef7fa0ab39b7dce61fa73f45e9972e59bd..71ae48eb022bf32341f74c857d55ce8dc3de2785 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<jmeterTestPlan version="1.2" properties="2.6" jmeter="2.11 r1554548"> +<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Toolkit" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> @@ -83,14 +83,14 @@ <stringProp name="Argument.value">${__P(admin_path,admin)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="admin_user" elementType="Argument"> - <stringProp name="Argument.name">admin_user</stringProp> - <stringProp name="Argument.value">${__P(admin_user,admin)}</stringProp> + <elementProp name="admin-user" elementType="Argument"> + <stringProp name="Argument.name">admin-user</stringProp> + <stringProp name="Argument.value">${__P(admin-user,admin)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="admin_password" elementType="Argument"> - <stringProp name="Argument.name">admin_password</stringProp> - <stringProp name="Argument.value">${__P(admin_password,123123q)}</stringProp> + <elementProp name="admin-password" elementType="Argument"> + <stringProp name="Argument.name">admin-password</stringProp> + <stringProp name="Argument.value">${__P(admin-password,123123q)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="website_id" elementType="Argument"> @@ -122,9 +122,10 @@ <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> <stringProp name="HTTPSampler.concurrentPool">4</stringProp> </ConfigTestElement> <hashTree/> @@ -249,7 +250,6 @@ if (!slash.equals(path.substring(path.length() -1)) || !slash.equals(path.substr <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> <stringProp name="TestPlan.comments">Site - Get Category 1</stringProp> @@ -322,7 +322,6 @@ props.put("category_name", vars.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -340,7 +339,7 @@ props.put("category_name", vars.get("category_name"));</stri <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">simple_products_url_keys</stringProp> - <stringProp name="RegexExtractor.regex"><a class="product-item-link" href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}">Simple</stringProp> + <stringProp name="RegexExtractor.regex"><a class="product-item-link"\s*href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}"></stringProp> <stringProp name="RegexExtractor.template">$2$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">-1</stringProp> @@ -369,7 +368,6 @@ props.put("category_name", vars.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -477,7 +475,6 @@ productList.add(productMap); </stringProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -495,7 +492,7 @@ productList.add(productMap); </stringProp> <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">configurable_products_url_keys</stringProp> - <stringProp name="RegexExtractor.regex"><a class="product-item-link" href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}">Configurable</stringProp> + <stringProp name="RegexExtractor.regex"><a class="product-item-link"\s*href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}">\s*Configurable</stringProp> <stringProp name="RegexExtractor.template">$2$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">-1</stringProp> @@ -524,7 +521,6 @@ productList.add(productMap); </stringProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -674,7 +670,6 @@ productList.add(productMap); </stringProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -729,14 +724,14 @@ productList.add(productMap); </stringProp> </elementProp> <elementProp name="login[password]" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${admin_password}</stringProp> + <stringProp name="Argument.value">${admin-password}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> <stringProp name="Argument.name">login[password]</stringProp> </elementProp> <elementProp name="login[username]" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${admin_user}</stringProp> + <stringProp name="Argument.value">${admin-user}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> <stringProp name="Argument.name">login[username]</stringProp> @@ -755,7 +750,6 @@ productList.add(productMap); </stringProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -786,7 +780,6 @@ productList.add(productMap); </stringProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -856,7 +849,6 @@ vars.put("searchData", new String(Base64Encoder.encode(searchData)));< <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -996,7 +988,6 @@ if (orders > 0) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1074,7 +1065,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1110,7 +1100,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1146,7 +1135,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1183,7 +1171,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1220,7 +1207,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1314,7 +1300,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1350,7 +1335,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1386,7 +1370,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1404,7 +1387,7 @@ vars.put("category_name", props.get("category_name"));</stri <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -1479,7 +1462,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1524,7 +1506,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1542,7 +1523,7 @@ vars.put("category_name", props.get("category_name"));</stri <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -1617,7 +1598,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1662,7 +1642,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1680,7 +1659,7 @@ vars.put("category_name", props.get("category_name"));</stri <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -1762,7 +1741,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1864,7 +1842,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1900,7 +1877,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1936,7 +1912,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -1954,7 +1929,7 @@ vars.put("category_name", props.get("category_name"));</stri <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -2029,7 +2004,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2074,7 +2048,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2092,7 +2065,7 @@ vars.put("category_name", props.get("category_name"));</stri <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -2167,7 +2140,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2212,7 +2184,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2230,7 +2201,7 @@ vars.put("category_name", props.get("category_name"));</stri <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -2312,7 +2283,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2357,7 +2327,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2444,7 +2413,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2630,7 +2598,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2697,7 +2664,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2771,7 +2737,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2837,7 +2802,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2873,7 +2837,6 @@ vars.put("category_name", props.get("category_name"));</stri <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -2983,7 +2946,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3019,7 +2981,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3055,7 +3016,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3073,7 +3033,7 @@ if (emailsCount < 1) { <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -3148,7 +3108,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3193,7 +3152,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3211,7 +3169,7 @@ if (emailsCount < 1) { <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -3286,7 +3244,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3331,7 +3288,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3349,7 +3305,7 @@ if (emailsCount < 1) { <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> <stringProp name="RegexExtractor.useHeaders">false</stringProp> <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)" method="post" id="product_addtocart_form"></stringProp> + <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> <stringProp name="RegexExtractor.template">$1$</stringProp> <stringProp name="RegexExtractor.default"></stringProp> <stringProp name="RegexExtractor.match_number">1</stringProp> @@ -3431,7 +3387,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3476,7 +3431,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3570,7 +3524,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3728,7 +3681,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3800,7 +3752,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3865,7 +3816,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3931,7 +3881,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -3967,7 +3916,6 @@ if (emailsCount < 1) { <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <stringProp name="HTTPSampler.implementation">Java</stringProp> <boolProp name="HTTPSampler.monitor">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> @@ -4054,6 +4002,9 @@ props.remove("customer_emails_list");</stringProp> <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename">${report_save_path}/view-results-tree.log</stringProp> @@ -4086,6 +4037,9 @@ props.remove("customer_emails_list");</stringProp> <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <url>true</url> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename">${report_save_path}/detailed-urls-report.log</stringProp> @@ -4118,6 +4072,9 @@ props.remove("customer_emails_list");</stringProp> <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> </value> </objProp> <stringProp name="filename">${report_save_path}/summary-report.log</stringProp> diff --git a/setup/performance-toolkit/profiles/ce/extra_large.xml b/setup/performance-toolkit/profiles/ce/extra_large.xml index 25575c3a77f66d0a75ec7ad2b4cb5d85938256b4..9d5767fbfba33f62963bed898213dc28ae30d95c 100644 --- a/setup/performance-toolkit/profiles/ce/extra_large.xml +++ b/setup/performance-toolkit/profiles/ce/extra_large.xml @@ -18,6 +18,8 @@ <cart_price_rules>100</cart_price_rules> <!-- Number of shopping cart price rules --> <cart_price_rules_floor>5</cart_price_rules_floor> <!-- The price rule condition: minimum products amount in shopping cart for price rule to be applied --> <customers>5000</customers> <!-- Number of customers to generate --> + <tax_rates_file>tax_rates.csv</tax_rates_file> <!-- Tax rates file in fixtures directory--> + <orders>80000</orders> <!-- Orders count --> <configs> <!-- Config variables and values for change --> <config> <path>admin/security/use_form_key</path> @@ -32,5 +34,39 @@ <value>1</value> </config> </configs> + <indexers> <!-- Indexer mode value (true - Update by Schedule, false - Update on Save) --> + <indexer> + <id>catalog_category_product</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_category</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_price</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_attribute</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>cataloginventory_stock</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_rule</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_product</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalogsearch_fulltext</id> + <set_scheduled>true</set_scheduled> + </indexer> + </indexers> </profile> </config> diff --git a/setup/performance-toolkit/profiles/ce/large.xml b/setup/performance-toolkit/profiles/ce/large.xml index 093f2868fe3a738ef7647958f2c4360620e11162..bdbce2f2b8b7ca464606e3b5b351cc658f5ce624 100644 --- a/setup/performance-toolkit/profiles/ce/large.xml +++ b/setup/performance-toolkit/profiles/ce/large.xml @@ -18,6 +18,8 @@ <cart_price_rules>50</cart_price_rules> <!-- Number of shopping cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> <!-- The price rule condition: minimum products amount in shopping cart for price rule to be applied --> <customers>2000</customers> <!-- Number of customers to generate --> + <tax_rates_file>tax_rates.csv</tax_rates_file> <!-- Tax rates file in fixtures directory--> + <orders>40000</orders> <!-- Orders count --> <configs> <!-- Config variables and values for change --> <config> <path>admin/security/use_form_key</path> @@ -32,5 +34,39 @@ <value>1</value> </config> </configs> + <indexers> <!-- Indexer mode value (true - Update by Schedule, false - Update on Save) --> + <indexer> + <id>catalog_category_product</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_category</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_price</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_attribute</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>cataloginventory_stock</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_rule</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_product</id> + <set_scheduled>true</set_scheduled> + </indexer> + <indexer> + <id>catalogsearch_fulltext</id> + <set_scheduled>true</set_scheduled> + </indexer> + </indexers> </profile> </config> diff --git a/setup/performance-toolkit/profiles/ce/medium.xml b/setup/performance-toolkit/profiles/ce/medium.xml index edada57536f59043eb423dce5181a405676e49c4..8c91400d50bd697ab080985541bf35c760067642 100644 --- a/setup/performance-toolkit/profiles/ce/medium.xml +++ b/setup/performance-toolkit/profiles/ce/medium.xml @@ -18,6 +18,8 @@ <cart_price_rules>20</cart_price_rules> <!-- Number of shopping cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> <!-- The price rule condition: minimum products amount in shopping cart for price rule to be applied --> <customers>200</customers> <!-- Number of customers to generate --> + <tax_rates_file>tax_rates.csv</tax_rates_file> <!-- Tax rates file in fixtures directory--> + <orders>1600</orders> <!-- Orders count --> <configs> <!-- Config variables and values for change --> <config> <path>admin/security/use_form_key</path> @@ -32,5 +34,39 @@ <value>1</value> </config> </configs> + <indexers> <!-- Indexer mode value (true - Update by Schedule, false - Update on Save) --> + <indexer> + <id>catalog_category_product</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_category</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_price</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_attribute</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>cataloginventory_stock</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_rule</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_product</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogsearch_fulltext</id> + <set_scheduled>false</set_scheduled> + </indexer> + </indexers> </profile> </config> diff --git a/setup/performance-toolkit/profiles/ce/small.xml b/setup/performance-toolkit/profiles/ce/small.xml index 578d2feec9e43cf4337db2b6066e4e7a3d6cd66d..79f2605bc775d7c3fdb0fe92106df966c6330c0c 100644 --- a/setup/performance-toolkit/profiles/ce/small.xml +++ b/setup/performance-toolkit/profiles/ce/small.xml @@ -18,6 +18,8 @@ <cart_price_rules>10</cart_price_rules> <!-- Number of shopping cart price rules --> <cart_price_rules_floor>2</cart_price_rules_floor> <!-- The price rule condition: minimum products amount in shopping cart for price rule to be applied --> <customers>20</customers> <!-- Number of customers to generate --> + <tax_rates_file>tax_rates.csv</tax_rates_file> <!-- Tax rates file in fixtures directory--> + <orders>80</orders> <!-- Orders count --> <configs> <!-- Config variables and values for change --> <config> <path>admin/security/use_form_key</path> @@ -32,5 +34,39 @@ <value>1</value> </config> </configs> + <indexers> <!-- Indexer mode value (true - Update by Schedule, false - Update on Save) --> + <indexer> + <id>catalog_category_product</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_category</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_price</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalog_product_attribute</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>cataloginventory_stock</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_rule</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogrule_product</id> + <set_scheduled>false</set_scheduled> + </indexer> + <indexer> + <id>catalogsearch_fulltext</id> + <set_scheduled>false</set_scheduled> + </indexer> + </indexers> </profile> </config> diff --git a/setup/pub/styles/setup.css b/setup/pub/styles/setup.css index ebe7d360aa51a5727093b1b86326a529a7fc3c07..d667b416c7a211c9990db9a8b32bf896fdadc6a6 100644 --- a/setup/pub/styles/setup.css +++ b/setup/pub/styles/setup.css @@ -3,4 +3,4 @@ * See COPYING.txt for license details. */ -html{box-sizing:border-box;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}*,:after,:before{box-sizing:inherit}:focus{box-shadow:none;outline:0}._keyfocus :focus{box-shadow:0 0 0 1px #008bdb}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}embed,img,object,video{max-width:100%}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}:after,:before{box-sizing:content-box}.abs-clearer:after,.form-row:after,.header:after,.nav:after,.row:after{content:"";display:table;clear:both}.ng-cloak{display:none!important}.hide.hide{display:none}.show.show{display:block}.text-center{text-align:center}.text-right{text-align:right}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/light/opensans-300.eot);src:url(../../pub/fonts/opensans/light/opensans-300.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/light/opensans-300.woff2) format('woff2'),url(../../pub/fonts/opensans/light/opensans-300.woff) format('woff'),url(../../pub/fonts/opensans/light/opensans-300.ttf) format('truetype'),url('../../pub/fonts/opensans/light/opensans-300.svg#Open Sans') format('svg');font-weight:300;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/regular/opensans-400.eot);src:url(../../pub/fonts/opensans/regular/opensans-400.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/regular/opensans-400.woff2) format('woff2'),url(../../pub/fonts/opensans/regular/opensans-400.woff) format('woff'),url(../../pub/fonts/opensans/regular/opensans-400.ttf) format('truetype'),url('../../pub/fonts/opensans/regular/opensans-400.svg#Open Sans') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/semibold/opensans-600.eot);src:url(../../pub/fonts/opensans/semibold/opensans-600.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/semibold/opensans-600.woff2) format('woff2'),url(../../pub/fonts/opensans/semibold/opensans-600.woff) format('woff'),url(../../pub/fonts/opensans/semibold/opensans-600.ttf) format('truetype'),url('../../pub/fonts/opensans/semibold/opensans-600.svg#Open Sans') format('svg');font-weight:600;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/bold/opensans-700.eot);src:url(../../pub/fonts/opensans/bold/opensans-700.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/bold/opensans-700.woff2) format('woff2'),url(../../pub/fonts/opensans/bold/opensans-700.woff) format('woff'),url(../../pub/fonts/opensans/bold/opensans-700.ttf) format('truetype'),url('../../pub/fonts/opensans/bold/opensans-700.svg#Open Sans') format('svg');font-weight:700;font-style:normal}html{font-size:62.5%}body{color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:400;line-height:1.4}h1,h2,h3,h4,h5,h6{font-weight:400;margin-top:0}p{margin:0 0 1em}a{color:#008bdb;text-decoration:none}a:hover{color:#0fa7ff;text-decoration:underline}@font-face{font-family:Icons;src:url(../../pub/fonts/icons/icons.eot);src:url(../../pub/fonts/icons/icons.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/icons/icons.woff2) format('woff2'),url(../../pub/fonts/icons/icons.woff) format('woff'),url(../../pub/fonts/icons/icons.ttf) format('truetype'),url(../../pub/fonts/icons/icons.svg#Icons) format('svg');font-weight:400;font-style:normal}[class*=icon-]{display:inline-block;line-height:1}[class*=icon-]:after{font-family:Icons}.icon-success-thick:after{content:'\e600'}.icon-success:after{content:'\e601'}.icon-collapse:after{content:'\e602'}.icon-failed-thick:after{content:'\e603'}.icon-failed:after{content:'\e604'}.icon-expand:after{content:'\e605'}.icon-warning:after{content:'\e606'}.icon-failed-round,.icon-success-round{border-radius:100%;color:#fff;font-size:2.5rem;height:1em;position:relative;text-align:center;width:1em}.icon-failed-round:after,.icon-success-round:after{bottom:0;font-size:.8em;left:0;position:absolute;right:0;top:.15em}.icon-success-round{background-color:#79a22e}.icon-success-round:after{content:'\e600'}.icon-failed-round{background-color:#e22626}.icon-failed-round:after{content:'\e603'}dl,ol,ul{margin-top:0}.list{margin-bottom:1em;padding-left:0}.list>li{display:block;margin-bottom:.75em;position:relative}.list>li>.icon-failed,.list>li>.icon-success{font-size:1.6em;left:-.1em;position:absolute;top:0}.list>li>.icon-success{color:#79a22e}.list>li>.icon-failed{color:#e22626}.list-item-failed,.list-item-icon,.list-item-success{padding-left:3.5rem}.list-item-failed:before,.list-item-success:before{font-family:Icons;font-size:1.6em;left:-.1em;position:absolute;top:-.2em}.list-item-success:before{color:#79a22e;content:'\e601'}.list-item-failed:before{color:#e22626;content:'\e604'}.list-definition{margin:0 0 3rem;padding:0}.list-definition>dt{clear:left;float:left}.list-definition>dd{margin-bottom:1em;margin-left:20rem}.btn-wrap{margin:0 auto}.btn-wrap .btn{width:100%}.btn{background:#e3e3e3;border:none;color:#514943;display:inline-block;font-size:1.6rem;font-weight:600;padding:.45em .5em;text-align:center}.btn:hover{background-color:#dbdbdb;color:#514943;text-decoration:none}.btn:active{background-color:#d6d6d6}.btn.disabled,.btn[disabled]{cursor:default;opacity:.5;pointer-events:none}.ie9 .btn.disabled,.ie9 .btn[disabled]{background-color:#f0f0f0;opacity:1;text-shadow:none}.btn-large{padding:.75em 1.25em}.btn-link{background-color:transparent;border:none;color:#008bdb;font-family:1.6rem;font-size:1.5rem}.btn-link:hover{background-color:transparent;color:#0fa7ff}.btn-prime{background-color:#eb5202;color:#fff;text-shadow:1px 1px 0 rgba(0,0,0,.25)}.btn-prime:hover{background-color:#f65405;background-repeat:repeat-x;background-image:linear-gradient(to right,#e04f00 0,#f65405 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e04f00', endColorstr='#f65405', GradientType=1);color:#fff}.btn-prime:active{background-color:#e04f00;background-repeat:repeat-x;background-image:linear-gradient(to right,#f65405 0,#e04f00 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f65405', endColorstr='#e04f00', GradientType=1)}.ie9 .btn-prime.disabled,.ie9 .btn-prime[disabled]{background-color:#fd6e23}.ie9 .btn-prime.disabled:active,.ie9 .btn-prime.disabled:hover,.ie9 .btn-prime[disabled]:active,.ie9 .btn-prime[disabled]:hover{background-color:#fd6e23;-webkit-filter:none;filter:none}.btn-secondary{background-color:#514943;color:#fff}.btn-secondary:hover{background-color:#5f564f;color:#fff}.btn-secondary:active{background-color:#574e48}.ie9 .btn-secondary.disabled,.ie9 .btn-secondary[disabled]{background-color:#514943}.ie9 .btn-secondary.disabled:active,.ie9 .btn-secondary.disabled:hover,.ie9 .btn-secondary[disabled]:active,.ie9 .btn-secondary[disabled]:hover{background-color:#514943;-webkit-filter:none;filter:none}[class*=btn-wrap-triangle]{overflow:hidden;position:relative}[class*=btn-wrap-triangle] .btn:after{border-style:solid;content:'';height:0;position:absolute;top:0;width:0}.btn-wrap-triangle-right{display:inline-block;padding-right:1.74rem;position:relative}.btn-wrap-triangle-right .btn{text-indent:.92rem}.btn-wrap-triangle-right .btn:after{border-color:transparent transparent transparent #e3e3e3;border-width:1.84rem 0 1.84rem 1.84rem;left:100%;margin-left:-1.74rem}.btn-wrap-triangle-right .btn:hover:after{border-left-color:#dbdbdb}.btn-wrap-triangle-right .btn:active:after{border-left-color:#d6d6d6}.btn-wrap-triangle-right .btn:not(.disabled):active,.btn-wrap-triangle-right .btn:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn.disabled:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:after{border-color:transparent transparent transparent #f0f0f0}.ie9 .btn-wrap-triangle-right .btn.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:hover:after{border-left-color:#f0f0f0}.btn-wrap-triangle-right .btn-prime:after{border-color:transparent transparent transparent #eb5202}.btn-wrap-triangle-right .btn-prime:hover:after{border-left-color:#f65405}.btn-wrap-triangle-right .btn-prime:active:after{border-left-color:#e04f00}.btn-wrap-triangle-right .btn-prime:not(.disabled):active,.btn-wrap-triangle-right .btn-prime:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:after{border-color:transparent transparent transparent #fd6e23}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:hover:after{border-left-color:#fd6e23}.btn-wrap-triangle-left{display:inline-block;padding-left:1.74rem}.btn-wrap-triangle-left .btn{text-indent:-.92rem}.btn-wrap-triangle-left .btn:after{border-color:transparent #e3e3e3 transparent transparent;border-width:1.84rem 1.84rem 1.84rem 0;margin-right:-1.74rem;right:100%}.btn-wrap-triangle-left .btn:hover:after{border-right-color:#dbdbdb}.btn-wrap-triangle-left .btn:active:after{border-right-color:#d6d6d6}.btn-wrap-triangle-left .btn:not(.disabled):active,.btn-wrap-triangle-left .btn:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn.disabled:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:after{border-color:transparent #f0f0f0 transparent transparent}.ie9 .btn-wrap-triangle-left .btn.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:hover:after{border-right-color:#f0f0f0}.btn-wrap-triangle-left .btn-prime:after{border-color:transparent #eb5202 transparent transparent}.btn-wrap-triangle-left .btn-prime:hover:after{border-right-color:#e04f00}.btn-wrap-triangle-left .btn-prime:active:after{border-right-color:#f65405}.btn-wrap-triangle-left .btn-prime:not(.disabled):active,.btn-wrap-triangle-left .btn-prime:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:after{border-color:transparent #fd6e23 transparent transparent}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:hover:after{border-right-color:#fd6e23}.btn-expand{background-color:transparent;border:none;color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;padding:0;position:relative}.btn-expand.expanded:after{border-color:transparent transparent #303030;border-width:0 .285em .36em}.btn-expand.expanded:hover:after{border-color:transparent transparent #3d3d3d}.btn-expand:hover{background-color:transparent;border:none;color:#3d3d3d}.btn-expand:hover:after{border-color:#3d3d3d transparent transparent}.btn-expand:after{border-color:#303030 transparent transparent;border-style:solid;border-width:.36em .285em 0;content:'';height:0;left:100%;margin-left:.5em;margin-top:-.18em;position:absolute;top:50%;width:0}[class*=col-] .form-el-input,[class*=col-] .form-el-select{width:100%}.form-fieldset{border:none;margin:0 0 1em;padding:0}.form-row{margin-bottom:2.2rem}.form-row .form-row{margin-bottom:.4rem}.form-row .form-label{display:block;font-weight:600;padding:.6rem 2.1em 0 0;text-align:right}.form-row .form-label.required{position:relative}.form-row .form-label.required:after{color:#eb5202;content:'*';font-size:1.15em;position:absolute;right:.7em;top:.5em}.form-row .form-el-checkbox+.form-label:before,.form-row .form-el-radio+.form-label:before{top:.7rem}.form-row .form-el-checkbox+.form-label:after,.form-row .form-el-radio+.form-label:after{top:1.1rem}input:not([disabled]):focus,textarea:not([disabled]):focus{box-shadow:none}.form-el-input{border:1px solid #adadad;border-radius:2px;color:#303030;padding:.35em .55em .5em}.form-el-input:hover{border-color:#949494}.form-el-input:focus{border-color:#008bdb}.form-label{margin-bottom:.5em}[class*=form-label][for]{cursor:pointer}.form-el-insider-wrap{display:table;width:100%}.form-el-insider-input{display:table-cell;width:100%}.form-el-insider{border-radius:2px;display:table-cell;vertical-align:top;padding:.43em .55em .5em 0}.form-legend,.form-legend-expand,.form-legend-light{display:block;margin:0}.form-legend,.form-legend-expand{margin-bottom:2.5em;padding-top:1.5em;font-weight:600;font-size:1.25em}.form-legend{width:100%;border-top:1px solid #ccc}.form-legend-light{margin-bottom:1.5em;font-size:1em}.form-legend-expand{transition:opacity .2s linear;cursor:pointer}.form-legend-expand:hover{opacity:.85}.form-legend-expand.expanded:after{content:'\e602'}.form-legend-expand:after{margin-left:.5em;font-weight:400;font-size:1.15em;font-family:Icons;content:'\e605';vertical-align:sub}.form-el-checkbox,.form-el-radio{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.form-el-checkbox.disabled+.form-label,.form-el-checkbox.disabled+.form-label:before,.form-el-checkbox[disabled]+.form-label,.form-el-checkbox[disabled]+.form-label:before,.form-el-radio.disabled+.form-label,.form-el-radio.disabled+.form-label:before,.form-el-radio[disabled]+.form-label,.form-el-radio[disabled]+.form-label:before{cursor:default;opacity:.5;pointer-events:none}.form-el-checkbox:not(.disabled)+.form-label:hover:before,.form-el-checkbox:not([disabled])+.form-label:hover:before,.form-el-radio:not(.disabled)+.form-label:hover:before,.form-el-radio:not([disabled])+.form-label:hover:before{border-color:#514943}.form-el-checkbox+.form-label,.form-el-radio+.form-label{font-weight:400;padding-left:2em;padding-right:0;position:relative;text-align:left;transition:border-color .1s linear}.form-el-checkbox+.form-label:before,.form-el-radio+.form-label:before{border:1px solid;content:'';left:0;position:absolute;top:.1rem;transition:border-color .1s linear}.form-el-checkbox+.form-label:before{border-color:#adadad;border-radius:2px;height:1.4rem;line-height:1;width:1.4rem}.form-el-checkbox:checked+.form-label::before{content:'\e600';font-family:Icons}.form-el-radio+.form-label:before{background-color:#fff;border:1px solid #adadad;border-radius:100%;height:1.6rem;width:1.6rem}.form-el-radio+.form-label:after{background:0 0;border:.5rem solid transparent;border-radius:100%;content:'';height:0;left:.4rem;position:absolute;top:.5rem;transition:background .3s linear;width:0}.form-el-radio:checked+.form-label{cursor:default}.form-el-radio:checked+.form-label:after{border-color:#514943}.form-select-label{border:1px solid #adadad;border-radius:2px;color:#303030;cursor:pointer;display:block;overflow:hidden;position:relative}.form-select-label:hover,.form-select-label:hover:after{border-color:#949494}.form-select-label:active,.form-select-label:active:after,.form-select-label:focus,.form-select-label:focus:after{border-color:#008bdb}.form-select-label:after{background:#e3e3e3;border-left:1px solid #adadad;bottom:0;content:'';position:absolute;right:0;top:0;width:2.36em;z-index:-2}.ie9 .form-select-label:after{display:none}.form-select-label:before{border-color:#303030 transparent transparent;border-style:solid;border-width:5px 4px 0;content:'';height:0;margin-right:-4px;margin-top:-2.5px;position:absolute;right:1.18em;top:50%;width:0;z-index:-1}.ie9 .form-select-label:before{display:none}.form-select-label .form-el-select{background:0 0;border:none;border-radius:0;content:'';display:block;margin:0;padding:.35em calc(2.36em + 10%) .5em .55em;width:110%}.ie9 .form-select-label .form-el-select{padding-right:.55em;width:100%}.form-el-select{background:#fff;border:1px solid #adadad;border-radius:2px;color:#303030;display:block;padding:.35em .55em}.multiselect-custom{position:relative;height:45.2rem;border:1px solid #adadad;overflow:auto;margin:0 0 1.5rem}.multiselect-custom ul{margin:0;padding:0;list-style:none;min-width:29rem}.multiselect-custom .item{padding:1rem 1.4rem}.multiselect-custom .selected{background-color:#e0f6fe}.multiselect-custom .form-label{margin-bottom:0}[class*=form-el-].invalid{border-color:#e22626}[class*=form-el-].invalid+.error-container{display:block}.error-container{background-color:#fffbbb;border:1px solid #ee7d7d;border-radius:2px;color:#514943;display:none;font-size:1.19rem;margin-top:.2rem;padding:.4235em .6655em .605em}.check-result-message{margin-left:.5em;min-height:3.68rem;-webkit-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.check-result-text{margin-left:.5em}.pseudo-table{display:table}.pseudo-td{display:table-cell}.messages{margin:0 0 2rem}.message{background:#fffbbb;border:none;border-radius:0;color:#333;font-size:14px;margin:0 0 1px;padding:1.8rem 4rem 1.8rem 5.5rem;position:relative;text-shadow:none}.message:before{background:0 0;border:0;color:#007bdb;content:'\e61a';font-family:Icons;font-size:1.9rem;font-style:normal;font-weight:400;height:auto;left:1.9rem;line-height:inherit;margin-top:-1.3rem;position:absolute;speak:none;text-shadow:none;top:50%;width:auto}.message-notice:before{color:#007bdb;content:'\e61a'}.message-warning:before{color:#eb5202;content:'\e623'}.message-error{background:#fcc}.message-error:before{color:#e22626;content:'\e632';font-size:1.5rem;left:2.2rem;margin-top:-1rem}.message-success:before{color:#79a22e;content:'\e62d'}.message-spinner:before{display:none}.message-spinner .spinner{font-size:2.5rem;left:1.5rem;position:absolute;top:1.5rem}.message-in-rating-edit{margin-left:1.8rem;margin-right:1.8rem}.message{margin-bottom:3rem}.container{display:block;margin:0 auto 4rem;max-width:100rem;padding:0 2rem}.row{margin-left:0;margin-right:0}.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9,.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{min-height:1px;padding-left:0;padding-right:0;position:relative}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}.nav{background-color:#f8f8f8;border-bottom:1px solid #e3e3e3;border-top:1px solid #e3e3e3;display:none;padding:2.2rem 1.5rem 0 0}.nav .btn-group,.nav-bar-outer-actions{float:right;margin-bottom:1.7rem}.nav .btn-group .btn-wrap,.nav-bar-outer-actions .btn-wrap{float:right;margin-left:.5rem;margin-right:.5rem}.nav-bar-outer-actions{margin-top:-10.6rem;padding-right:1.5rem}.btn-wrap-try-again{width:9.5rem}.btn-wrap-next,.btn-wrap-prev{width:8.5rem}.nav-bar{counter-reset:i;float:left;margin:0 1rem 1.7rem 0;padding:0;position:relative;white-space:nowrap}.nav-bar:before{background-color:#d4d4d4;background-repeat:repeat-x;background-image:linear-gradient(to bottom,#d1d1d1 0,#d4d4d4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d1d1d1', endColorstr='#d4d4d4', GradientType=0);border-bottom:1px solid #d9d9d9;border-top:1px solid #bfbfbf;content:'';height:.8rem;left:5.15rem;position:absolute;right:5.15rem;top:.7rem}.nav-bar>li{display:inline-block;font-size:0;position:relative;vertical-align:top;width:10.3rem}.nav-bar>li:first-child:after{display:none}.nav-bar>li:after{background-color:#514943;content:'';height:.5rem;left:calc(-50% + .25rem);position:absolute;right:calc(50% + .7rem);top:.9rem}.nav-bar>li.disabled:before{bottom:0;content:'';left:0;position:absolute;right:0;top:0;z-index:1}.nav-bar>li.active~li:after{display:none}.nav-bar>li.active~li a:after{background-color:transparent;border-color:transparent;color:#a6a6a6}.nav-bar>li.active a{color:#000}.nav-bar>li.active a:hover{cursor:default}.nav-bar>li.active a:after{background-color:#fff;content:''}.nav-bar a{color:#514943;display:block;font-size:1.2rem;font-weight:600;line-height:1.2;overflow:hidden;padding:3rem .5em 0;position:relative;text-align:center;text-overflow:ellipsis}.nav-bar a:hover{text-decoration:none}.nav-bar a:after{background-color:#514943;border:.4rem solid #514943;border-radius:100%;color:#fff;content:counter(i);counter-increment:i;height:.7rem;left:50%;line-height:.6;margin-left:-.8rem;position:absolute;right:auto;text-align:center;top:.4rem;width:.7rem}.nav-bar a:before{background-color:#d6d6d6;border:1px solid transparent;border-bottom-color:#d9d9d9;border-radius:100%;border-top-color:#bfbfbf;content:'';height:2.1rem;left:50%;line-height:1;margin-left:-1.2rem;position:absolute;top:0;width:2.1rem}.tooltip{display:block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.19rem;font-weight:400;line-height:1.4;opacity:0;position:absolute;visibility:visible;z-index:10}.tooltip.in{opacity:.9}.tooltip.top{margin-top:-4px;padding:8px 0}.tooltip.right{margin-left:4px;padding:0 8px}.tooltip.bottom{margin-top:4px;padding:8px 0}.tooltip.left{margin-left:-4px;padding:0 8px}.tooltip-inner{background-color:#fff;border:1px solid #adadad;border-radius:0;box-shadow:1px 1px 1px #ccc;color:#41362f;max-width:20rem;padding:.5em 1em;text-decoration:none}.tooltip-arrow,.tooltip-arrow:after{border:solid transparent;height:0;position:absolute;width:0}.tooltip-arrow:after{content:'';position:absolute}.tooltip.top .tooltip-arrow,.tooltip.top .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:50%;margin-left:-8px}.tooltip.top-left .tooltip-arrow,.tooltip.top-left .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;margin-bottom:-8px;right:8px}.tooltip.top-right .tooltip-arrow,.tooltip.top-right .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:8px;margin-bottom:-8px}.tooltip.right .tooltip-arrow,.tooltip.right .tooltip-arrow:after{border-right-color:#949494;border-width:8px 8px 8px 0;left:1px;margin-top:-8px;top:50%}.tooltip.right .tooltip-arrow:after{border-right-color:#fff;border-width:6px 7px 6px 0;margin-left:0;margin-top:-6px}.tooltip.left .tooltip-arrow,.tooltip.left .tooltip-arrow:after{border-left-color:#949494;border-width:8px 0 8px 8px;margin-top:-8px;right:0;top:50%}.tooltip.bottom .tooltip-arrow,.tooltip.bottom .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:50%;margin-left:-8px;top:0}.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;margin-top:-8px;right:8px;top:0}.tooltip.bottom-right .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:8px;margin-top:-8px;top:0}.password-strength{display:block;margin:0 -.3rem 1em;white-space:nowrap}.password-strength.password-strength-too-short .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child+.password-strength-item{background-color:#e22626}.password-strength.password-strength-fair .password-strength-item:first-child,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item+.password-strength-item{background-color:#ef672f}.password-strength.password-strength-good .password-strength-item:first-child,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item+.password-strength-item,.password-strength.password-strength-strong .password-strength-item{background-color:#79a22e}.password-strength .password-strength-item{background-color:#ccc;display:inline-block;font-size:0;height:1.4rem;margin-right:.3rem;width:calc(20% - .6rem)}@-webkit-keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}.progress{background-color:#fafafa;border:1px solid #ccc;height:3rem;margin-bottom:3rem;overflow:hidden}.progress-bar{background-color:#79a22e;color:#fff;float:left;font-size:1.19rem;height:100%;line-height:3rem;text-align:center;transition:width .6s ease;width:0}.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.spinner{display:inline-block;font-size:4rem;height:1em;margin-right:1.5rem;position:relative;width:1em}@-webkit-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@-ms-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}.spinner>span:nth-child(1){-webkit-animation-delay:.27s;-ms-animation-delay:.27s;animation-delay:.27s;-webkit-transform:rotate(-315deg);-ms-transform:rotate(-315deg);transform:rotate(-315deg)}.spinner>span:nth-child(2){-webkit-animation-delay:.36s;-ms-animation-delay:.36s;animation-delay:.36s;-webkit-transform:rotate(-270deg);-ms-transform:rotate(-270deg);transform:rotate(-270deg)}.spinner>span:nth-child(3){-webkit-animation-delay:.45s;-ms-animation-delay:.45s;animation-delay:.45s;-webkit-transform:rotate(-225deg);-ms-transform:rotate(-225deg);transform:rotate(-225deg)}.spinner>span:nth-child(4){-webkit-animation-delay:.54s;-ms-animation-delay:.54s;animation-delay:.54s;-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.spinner>span:nth-child(5){-webkit-animation-delay:.63s;-ms-animation-delay:.63s;animation-delay:.63s;-webkit-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.spinner>span:nth-child(6){-webkit-animation-delay:.72s;-ms-animation-delay:.72s;animation-delay:.72s;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.spinner>span:nth-child(7){-webkit-animation-delay:.81s;-ms-animation-delay:.81s;animation-delay:.81s;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.spinner>span:nth-child(8){-webkit-animation-delay:.9;-ms-animation-delay:.9;animation-delay:.9;-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}.spinner>span{-webkit-animation-direction:linear;-ms-animation-direction:linear;animation-direction:linear;-webkit-animation-duration:.72s;-ms-animation-duration:.72s;animation-duration:.72s;-webkit-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fade;-ms-animation-name:fade;animation-name:fade;-webkit-transform:scale(0.4);-ms-transform:scale(0.4);transform:scale(0.4);background-color:#fff;border-radius:6px;clip:rect(0 .28571429em .1em 0);height:.1em;margin-top:.5em;position:absolute;width:1em}.ie9 .spinner{background:url(../../pub/images/ajax-loader.gif) center no-repeat}.ie9 .spinner>span{display:none}.main{padding-bottom:2rem;padding-top:3rem}.header{display:none}.header .logo{float:left;height:4.1rem;width:3.5rem}.header-title{font-size:2.8rem;letter-spacing:.02em;margin:2.5rem 0 3.5rem 5rem}.page-title{font-size:2rem;margin-bottom:1.3em}.accent-box{margin-bottom:2rem}.accent-box .btn-prime{margin-top:1.5rem}.page-landing{margin:7.6% auto 0;max-width:44rem;text-align:center}.page-landing .logo{height:5.6rem;margin-bottom:2rem;width:19.2rem}.page-landing .text-version{margin-bottom:3rem}.page-landing .text-welcome{margin-bottom:6.5rem}.page-landing .text-terms{margin-bottom:2.5rem;text-align:center}.page-landing .btn-submit{margin-bottom:20px}.page-license .license-text{margin-bottom:2rem}.page-license .page-license-footer{text-align:right}.rediness-check-item{margin-bottom:4rem}.readiness-check-title{font-size:1.4rem;font-weight:700;margin-bottom:.1rem;margin-left:7.5rem}.readiness-check-content{margin-left:7.5rem;margin-right:22rem}.readiness-check-content .readiness-check-title{margin-left:0}.readiness-check-content .list{margin-top:-.3rem}.rediness-check-side{float:right;padding-left:2.4rem;width:22rem}.rediness-check-side .side-title{margin-bottom:0}.readiness-check-icon{float:left;margin-left:2rem;margin-top:.7rem}.page-web-configuration .form-el-insider-wrap{width:auto}.page-web-configuration .form-el-insider{width:15.4rem}.page-web-configuration .form-el-insider-input .form-el-input{width:16.5rem}.customize-your-store .customize-your-store-default .legend{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.customize-your-store .advanced-modules-count,.customize-your-store .advanced-modules-select{padding-left:1.5rem}.customize-your-store .customize-your-store-advanced{min-width:0}.customize-your-store .message-error:before{margin-top:0;top:1.8rem}.customize-your-store .message-error a{color:#333;text-decoration:underline}.customize-your-store .message-error .form-label:before{background:#fff}.content-install{margin-bottom:2rem}.console{border:1px solid #ccc;font-family:'Courier New',Courier,monospace;font-weight:300;margin:1rem 0 2rem;max-height:20rem;overflow-y:auto;padding:1.5rem 2rem 2rem}.console .text-danger{color:#e22626}.console .text-success{color:#090}.console .hidden{display:none}.content-success .btn-prime{margin-top:1.5rem}.jumbo-title{font-size:3.6rem}.jumbo-title .jumbo-icon{font-size:3.8rem;margin-right:.25em;position:relative;top:.15em}@media all and (max-width:1047px){.nav{padding-bottom:5.38rem;padding-left:1.5rem;text-align:center}.nav-bar{display:inline-block;float:none;margin-right:0;vertical-align:top}.nav .btn-group,.nav-bar-outer-actions{display:inline-block;float:none;margin-top:-8.48rem;text-align:center;vertical-align:top;width:100%}.nav-bar-outer-actions{padding-right:0}.nav-bar-outer-actions .outer-actions-inner-wrap{display:inline-block}}@media all and (min-width:768px){.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9{float:left}.col-m-12{width:100%}.col-m-11{width:91.66666667%}.col-m-10{width:83.33333333%}.col-m-9{width:75%}.col-m-8{width:66.66666667%}.col-m-7{width:58.33333333%}.col-m-6{width:50%}.col-m-5{width:41.66666667%}.col-m-4{width:33.33333333%}.col-m-3{width:25%}.col-m-2{width:16.66666667%}.col-m-1{width:8.33333333%}.col-m-pull-12{right:100%}.col-m-pull-11{right:91.66666667%}.col-m-pull-10{right:83.33333333%}.col-m-pull-9{right:75%}.col-m-pull-8{right:66.66666667%}.col-m-pull-7{right:58.33333333%}.col-m-pull-6{right:50%}.col-m-pull-5{right:41.66666667%}.col-m-pull-4{right:33.33333333%}.col-m-pull-3{right:25%}.col-m-pull-2{right:16.66666667%}.col-m-pull-1{right:8.33333333%}.col-m-pull-0{right:auto}.col-m-push-12{left:100%}.col-m-push-11{left:91.66666667%}.col-m-push-10{left:83.33333333%}.col-m-push-9{left:75%}.col-m-push-8{left:66.66666667%}.col-m-push-7{left:58.33333333%}.col-m-push-6{left:50%}.col-m-push-5{left:41.66666667%}.col-m-push-4{left:33.33333333%}.col-m-push-3{left:25%}.col-m-push-2{left:16.66666667%}.col-m-push-1{left:8.33333333%}.col-m-push-0{left:auto}.col-m-offset-12{margin-left:100%}.col-m-offset-11{margin-left:91.66666667%}.col-m-offset-10{margin-left:83.33333333%}.col-m-offset-9{margin-left:75%}.col-m-offset-8{margin-left:66.66666667%}.col-m-offset-7{margin-left:58.33333333%}.col-m-offset-6{margin-left:50%}.col-m-offset-5{margin-left:41.66666667%}.col-m-offset-4{margin-left:33.33333333%}.col-m-offset-3{margin-left:25%}.col-m-offset-2{margin-left:16.66666667%}.col-m-offset-1{margin-left:8.33333333%}.col-m-offset-0{margin-left:0}}@media all and (min-width:1048px){.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9{float:left}.col-l-12{width:100%}.col-l-11{width:91.66666667%}.col-l-10{width:83.33333333%}.col-l-9{width:75%}.col-l-8{width:66.66666667%}.col-l-7{width:58.33333333%}.col-l-6{width:50%}.col-l-5{width:41.66666667%}.col-l-4{width:33.33333333%}.col-l-3{width:25%}.col-l-2{width:16.66666667%}.col-l-1{width:8.33333333%}.col-l-pull-12{right:100%}.col-l-pull-11{right:91.66666667%}.col-l-pull-10{right:83.33333333%}.col-l-pull-9{right:75%}.col-l-pull-8{right:66.66666667%}.col-l-pull-7{right:58.33333333%}.col-l-pull-6{right:50%}.col-l-pull-5{right:41.66666667%}.col-l-pull-4{right:33.33333333%}.col-l-pull-3{right:25%}.col-l-pull-2{right:16.66666667%}.col-l-pull-1{right:8.33333333%}.col-l-pull-0{right:auto}.col-l-push-12{left:100%}.col-l-push-11{left:91.66666667%}.col-l-push-10{left:83.33333333%}.col-l-push-9{left:75%}.col-l-push-8{left:66.66666667%}.col-l-push-7{left:58.33333333%}.col-l-push-6{left:50%}.col-l-push-5{left:41.66666667%}.col-l-push-4{left:33.33333333%}.col-l-push-3{left:25%}.col-l-push-2{left:16.66666667%}.col-l-push-1{left:8.33333333%}.col-l-push-0{left:auto}.col-l-offset-12{margin-left:100%}.col-l-offset-11{margin-left:91.66666667%}.col-l-offset-10{margin-left:83.33333333%}.col-l-offset-9{margin-left:75%}.col-l-offset-8{margin-left:66.66666667%}.col-l-offset-7{margin-left:58.33333333%}.col-l-offset-6{margin-left:50%}.col-l-offset-5{margin-left:41.66666667%}.col-l-offset-4{margin-left:33.33333333%}.col-l-offset-3{margin-left:25%}.col-l-offset-2{margin-left:16.66666667%}.col-l-offset-1{margin-left:8.33333333%}.col-l-offset-0{margin-left:0}}@media all and (min-width:1440px){.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{float:left}.col-xl-12{width:100%}.col-xl-11{width:91.66666667%}.col-xl-10{width:83.33333333%}.col-xl-9{width:75%}.col-xl-8{width:66.66666667%}.col-xl-7{width:58.33333333%}.col-xl-6{width:50%}.col-xl-5{width:41.66666667%}.col-xl-4{width:33.33333333%}.col-xl-3{width:25%}.col-xl-2{width:16.66666667%}.col-xl-1{width:8.33333333%}.col-xl-pull-12{right:100%}.col-xl-pull-11{right:91.66666667%}.col-xl-pull-10{right:83.33333333%}.col-xl-pull-9{right:75%}.col-xl-pull-8{right:66.66666667%}.col-xl-pull-7{right:58.33333333%}.col-xl-pull-6{right:50%}.col-xl-pull-5{right:41.66666667%}.col-xl-pull-4{right:33.33333333%}.col-xl-pull-3{right:25%}.col-xl-pull-2{right:16.66666667%}.col-xl-pull-1{right:8.33333333%}.col-xl-pull-0{right:auto}.col-xl-push-12{left:100%}.col-xl-push-11{left:91.66666667%}.col-xl-push-10{left:83.33333333%}.col-xl-push-9{left:75%}.col-xl-push-8{left:66.66666667%}.col-xl-push-7{left:58.33333333%}.col-xl-push-6{left:50%}.col-xl-push-5{left:41.66666667%}.col-xl-push-4{left:33.33333333%}.col-xl-push-3{left:25%}.col-xl-push-2{left:16.66666667%}.col-xl-push-1{left:8.33333333%}.col-xl-push-0{left:auto}.col-xl-offset-12{margin-left:100%}.col-xl-offset-11{margin-left:91.66666667%}.col-xl-offset-10{margin-left:83.33333333%}.col-xl-offset-9{margin-left:75%}.col-xl-offset-8{margin-left:66.66666667%}.col-xl-offset-7{margin-left:58.33333333%}.col-xl-offset-6{margin-left:50%}.col-xl-offset-5{margin-left:41.66666667%}.col-xl-offset-4{margin-left:33.33333333%}.col-xl-offset-3{margin-left:25%}.col-xl-offset-2{margin-left:16.66666667%}.col-xl-offset-1{margin-left:8.33333333%}.col-xl-offset-0{margin-left:0}}@media all and (max-width:767px){.list-definition>dt{float:none}.list-definition>dd{margin-left:0}.form-row .form-label{text-align:left}.form-row .form-label.required:after{position:static}.nav{padding-bottom:0;padding-left:0;padding-right:0}.nav-bar-outer-actions{margin-top:0}.nav-bar{display:block;margin-bottom:0;margin-left:auto;margin-right:auto;width:30.9rem}.nav-bar:before{display:none}.nav-bar>li{float:left;min-height:9rem}.nav-bar>li:after{display:none}.nav-bar>li:nth-child(4n){clear:both}.nav-bar a{line-height:1.4}.tooltip{display:none!important}.readiness-check-content{margin-right:2rem}.form-el-insider,.form-el-insider-wrap,.page-web-configuration .form-el-insider-input,.page-web-configuration .form-el-insider-input .form-el-input{display:block;width:100%}}@media all and (max-width:479px){.nav-bar{width:23.175rem}.nav-bar>li{width:7.725rem}.nav .btn-group .btn-wrap-try-again,.nav-bar-outer-actions .btn-wrap-try-again{clear:both;display:block;float:none;margin-left:auto;margin-right:auto;margin-top:1rem;padding-top:1rem}} \ No newline at end of file +html{box-sizing:border-box;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}*,:after,:before{box-sizing:inherit}:focus{box-shadow:none;outline:0}._keyfocus :focus{box-shadow:0 0 0 1px #008bdb}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}embed,img,object,video{max-width:100%}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}:after,:before{box-sizing:content-box}.abs-clearer:after,.form-row:after,.header:after,.nav:after,.row:after{content:"";display:table;clear:both}.ng-cloak{display:none!important}.hide.hide{display:none}.show.show{display:block}.text-center{text-align:center}.text-right{text-align:right}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/light/opensans-300.eot);src:url(../../pub/fonts/opensans/light/opensans-300.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/light/opensans-300.woff2) format('woff2'),url(../../pub/fonts/opensans/light/opensans-300.woff) format('woff'),url(../../pub/fonts/opensans/light/opensans-300.ttf) format('truetype'),url('../../pub/fonts/opensans/light/opensans-300.svg#Open Sans') format('svg');font-weight:300;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/regular/opensans-400.eot);src:url(../../pub/fonts/opensans/regular/opensans-400.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/regular/opensans-400.woff2) format('woff2'),url(../../pub/fonts/opensans/regular/opensans-400.woff) format('woff'),url(../../pub/fonts/opensans/regular/opensans-400.ttf) format('truetype'),url('../../pub/fonts/opensans/regular/opensans-400.svg#Open Sans') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/semibold/opensans-600.eot);src:url(../../pub/fonts/opensans/semibold/opensans-600.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/semibold/opensans-600.woff2) format('woff2'),url(../../pub/fonts/opensans/semibold/opensans-600.woff) format('woff'),url(../../pub/fonts/opensans/semibold/opensans-600.ttf) format('truetype'),url('../../pub/fonts/opensans/semibold/opensans-600.svg#Open Sans') format('svg');font-weight:600;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/bold/opensans-700.eot);src:url(../../pub/fonts/opensans/bold/opensans-700.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/bold/opensans-700.woff2) format('woff2'),url(../../pub/fonts/opensans/bold/opensans-700.woff) format('woff'),url(../../pub/fonts/opensans/bold/opensans-700.ttf) format('truetype'),url('../../pub/fonts/opensans/bold/opensans-700.svg#Open Sans') format('svg');font-weight:700;font-style:normal}html{font-size:62.5%}body{color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:400;line-height:1.4}h1,h2,h3,h4,h5,h6{font-weight:400;margin-top:0}p{margin:0 0 1em}a{color:#008bdb;text-decoration:none}a:hover{color:#0fa7ff;text-decoration:underline}@font-face{font-family:Icons;src:url(../../pub/fonts/icons/icons.eot);src:url(../../pub/fonts/icons/icons.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/icons/icons.woff2) format('woff2'),url(../../pub/fonts/icons/icons.woff) format('woff'),url(../../pub/fonts/icons/icons.ttf) format('truetype'),url(../../pub/fonts/icons/icons.svg#Icons) format('svg');font-weight:400;font-style:normal}[class*=icon-]{display:inline-block;line-height:1}[class*=icon-]:after{font-family:Icons}.icon-success-thick:after{content:'\e600'}.icon-success:after{content:'\e601'}.icon-collapse:after{content:'\e602'}.icon-failed-thick:after{content:'\e603'}.icon-failed:after{content:'\e604'}.icon-expand:after{content:'\e605'}.icon-warning:after{content:'\e606'}.icon-failed-round,.icon-success-round{border-radius:100%;color:#fff;font-size:2.5rem;height:1em;position:relative;text-align:center;width:1em}.icon-failed-round:after,.icon-success-round:after{bottom:0;font-size:.8em;left:0;position:absolute;right:0;top:.15em}.icon-success-round{background-color:#79a22e}.icon-success-round:after{content:'\e600'}.icon-failed-round{background-color:#e22626}.icon-failed-round:after{content:'\e603'}dl,ol,ul{margin-top:0}.list{margin-bottom:1em;padding-left:0}.list>li{display:block;margin-bottom:.75em;position:relative}.list>li>.icon-failed,.list>li>.icon-success{font-size:1.6em;left:-.1em;position:absolute;top:0}.list>li>.icon-success{color:#79a22e}.list>li>.icon-failed{color:#e22626}.list-item-failed,.list-item-icon,.list-item-success{padding-left:3.5rem}.list-item-failed:before,.list-item-success:before{font-family:Icons;font-size:1.6em;left:-.1em;position:absolute;top:-.2em}.list-item-success:before{color:#79a22e;content:'\e601'}.list-item-failed:before{color:#e22626;content:'\e604'}.list-definition{margin:0 0 3rem;padding:0}.list-definition>dt{clear:left;float:left}.list-definition>dd{margin-bottom:1em;margin-left:20rem}.btn-wrap{margin:0 auto}.btn-wrap .btn{width:100%}.btn{background:#e3e3e3;border:none;color:#514943;display:inline-block;font-size:1.6rem;font-weight:600;padding:.45em .5em;text-align:center}.btn:hover{background-color:#dbdbdb;color:#514943;text-decoration:none}.btn:active{background-color:#d6d6d6}.btn.disabled,.btn[disabled]{cursor:default;opacity:.5;pointer-events:none}.ie9 .btn.disabled,.ie9 .btn[disabled]{background-color:#f0f0f0;opacity:1;text-shadow:none}.btn-large{padding:.75em 1.25em}.btn-link{background-color:transparent;border:none;color:#008bdb;font-family:1.6rem;font-size:1.5rem}.btn-link:hover{background-color:transparent;color:#0fa7ff}.btn-prime{background-color:#eb5202;color:#fff;text-shadow:1px 1px 0 rgba(0,0,0,.25)}.btn-prime:hover{background-color:#f65405;background-repeat:repeat-x;background-image:linear-gradient(to right,#e04f00 0,#f65405 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e04f00', endColorstr='#f65405', GradientType=1);color:#fff}.btn-prime:active{background-color:#e04f00;background-repeat:repeat-x;background-image:linear-gradient(to right,#f65405 0,#e04f00 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f65405', endColorstr='#e04f00', GradientType=1)}.ie9 .btn-prime.disabled,.ie9 .btn-prime[disabled]{background-color:#fd6e23}.ie9 .btn-prime.disabled:active,.ie9 .btn-prime.disabled:hover,.ie9 .btn-prime[disabled]:active,.ie9 .btn-prime[disabled]:hover{background-color:#fd6e23;-webkit-filter:none;filter:none}.btn-secondary{background-color:#514943;color:#fff}.btn-secondary:hover{background-color:#5f564f;color:#fff}.btn-secondary:active{background-color:#574e48}.ie9 .btn-secondary.disabled,.ie9 .btn-secondary[disabled]{background-color:#514943}.ie9 .btn-secondary.disabled:active,.ie9 .btn-secondary.disabled:hover,.ie9 .btn-secondary[disabled]:active,.ie9 .btn-secondary[disabled]:hover{background-color:#514943;-webkit-filter:none;filter:none}[class*=btn-wrap-triangle]{overflow:hidden;position:relative}[class*=btn-wrap-triangle] .btn:after{border-style:solid;content:'';height:0;position:absolute;top:0;width:0}.btn-wrap-triangle-right{display:inline-block;padding-right:1.74rem;position:relative}.btn-wrap-triangle-right .btn{text-indent:.92rem}.btn-wrap-triangle-right .btn:after{border-color:transparent transparent transparent #e3e3e3;border-width:1.84rem 0 1.84rem 1.84rem;left:100%;margin-left:-1.74rem}.btn-wrap-triangle-right .btn:hover:after{border-left-color:#dbdbdb}.btn-wrap-triangle-right .btn:active:after{border-left-color:#d6d6d6}.btn-wrap-triangle-right .btn:not(.disabled):active,.btn-wrap-triangle-right .btn:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn.disabled:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:after{border-color:transparent transparent transparent #f0f0f0}.ie9 .btn-wrap-triangle-right .btn.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:hover:after{border-left-color:#f0f0f0}.btn-wrap-triangle-right .btn-prime:after{border-color:transparent transparent transparent #eb5202}.btn-wrap-triangle-right .btn-prime:hover:after{border-left-color:#f65405}.btn-wrap-triangle-right .btn-prime:active:after{border-left-color:#e04f00}.btn-wrap-triangle-right .btn-prime:not(.disabled):active,.btn-wrap-triangle-right .btn-prime:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:after{border-color:transparent transparent transparent #fd6e23}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:hover:after{border-left-color:#fd6e23}.btn-wrap-triangle-left{display:inline-block;padding-left:1.74rem}.btn-wrap-triangle-left .btn{text-indent:-.92rem}.btn-wrap-triangle-left .btn:after{border-color:transparent #e3e3e3 transparent transparent;border-width:1.84rem 1.84rem 1.84rem 0;margin-right:-1.74rem;right:100%}.btn-wrap-triangle-left .btn:hover:after{border-right-color:#dbdbdb}.btn-wrap-triangle-left .btn:active:after{border-right-color:#d6d6d6}.btn-wrap-triangle-left .btn:not(.disabled):active,.btn-wrap-triangle-left .btn:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn.disabled:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:after{border-color:transparent #f0f0f0 transparent transparent}.ie9 .btn-wrap-triangle-left .btn.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:hover:after{border-right-color:#f0f0f0}.btn-wrap-triangle-left .btn-prime:after{border-color:transparent #eb5202 transparent transparent}.btn-wrap-triangle-left .btn-prime:hover:after{border-right-color:#e04f00}.btn-wrap-triangle-left .btn-prime:active:after{border-right-color:#f65405}.btn-wrap-triangle-left .btn-prime:not(.disabled):active,.btn-wrap-triangle-left .btn-prime:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:after{border-color:transparent #fd6e23 transparent transparent}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:hover:after{border-right-color:#fd6e23}.btn-expand{background-color:transparent;border:none;color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;padding:0;position:relative}.btn-expand.expanded:after{border-color:transparent transparent #303030;border-width:0 .285em .36em}.btn-expand.expanded:hover:after{border-color:transparent transparent #3d3d3d}.btn-expand:hover{background-color:transparent;border:none;color:#3d3d3d}.btn-expand:hover:after{border-color:#3d3d3d transparent transparent}.btn-expand:after{border-color:#303030 transparent transparent;border-style:solid;border-width:.36em .285em 0;content:'';height:0;left:100%;margin-left:.5em;margin-top:-.18em;position:absolute;top:50%;width:0}[class*=col-] .form-el-input,[class*=col-] .form-el-select{width:100%}.form-fieldset{border:none;margin:0 0 1em;padding:0}.form-row{margin-bottom:2.2rem}.form-row .form-row{margin-bottom:.4rem}.form-row .form-label{display:block;font-weight:600;padding:.6rem 2.1em 0 0;text-align:right}.form-row .form-label.required{position:relative}.form-row .form-label.required:after{color:#eb5202;content:'*';font-size:1.15em;position:absolute;right:.7em;top:.5em}.form-row .form-el-checkbox+.form-label:before,.form-row .form-el-radio+.form-label:before{top:.7rem}.form-row .form-el-checkbox+.form-label:after,.form-row .form-el-radio+.form-label:after{top:1.1rem}input:not([disabled]):focus,textarea:not([disabled]):focus{box-shadow:none}.form-el-input{border:1px solid #adadad;border-radius:2px;color:#303030;padding:.35em .55em .5em}.form-el-input:hover{border-color:#949494}.form-el-input:focus{border-color:#008bdb}.form-label{margin-bottom:.5em}[class*=form-label][for]{cursor:pointer}.form-el-insider-wrap{display:table;width:100%}.form-el-insider-input{display:table-cell;width:100%}.form-el-insider{border-radius:2px;display:table-cell;vertical-align:top;padding:.43em .55em .5em 0}.form-legend,.form-legend-expand,.form-legend-light{display:block;margin:0}.form-legend,.form-legend-expand{margin-bottom:2.5em;padding-top:1.5em;font-weight:600;font-size:1.25em}.form-legend{width:100%;border-top:1px solid #ccc}.form-legend-light{margin-bottom:1.5em;font-size:1em}.form-legend-expand{transition:opacity .2s linear;cursor:pointer}.form-legend-expand:hover{opacity:.85}.form-legend-expand.expanded:after{content:'\e602'}.form-legend-expand:after{margin-left:.5em;font-weight:400;font-size:1.15em;font-family:Icons;content:'\e605';vertical-align:sub}.form-el-checkbox,.form-el-radio{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.form-el-checkbox.disabled+.form-label,.form-el-checkbox.disabled+.form-label:before,.form-el-checkbox[disabled]+.form-label,.form-el-checkbox[disabled]+.form-label:before,.form-el-radio.disabled+.form-label,.form-el-radio.disabled+.form-label:before,.form-el-radio[disabled]+.form-label,.form-el-radio[disabled]+.form-label:before{cursor:default;opacity:.5;pointer-events:none}.form-el-checkbox:not(.disabled)+.form-label:hover:before,.form-el-checkbox:not([disabled])+.form-label:hover:before,.form-el-radio:not(.disabled)+.form-label:hover:before,.form-el-radio:not([disabled])+.form-label:hover:before{border-color:#514943}.form-el-checkbox+.form-label,.form-el-radio+.form-label{font-weight:400;padding-left:2em;padding-right:0;position:relative;text-align:left;transition:border-color .1s linear}.form-el-checkbox+.form-label:before,.form-el-radio+.form-label:before{border:1px solid;content:'';left:0;position:absolute;top:.1rem;transition:border-color .1s linear}.form-el-checkbox+.form-label:before{border-color:#adadad;border-radius:2px;height:1.4rem;line-height:1;width:1.4rem}.form-el-checkbox:checked+.form-label::before{content:'\e600';font-family:Icons}.form-el-radio+.form-label:before{background-color:#fff;border:1px solid #adadad;border-radius:100%;height:1.6rem;width:1.6rem}.form-el-radio+.form-label:after{background:0 0;border:.5rem solid transparent;border-radius:100%;content:'';height:0;left:.4rem;position:absolute;top:.5rem;transition:background .3s linear;width:0}.form-el-radio:checked+.form-label{cursor:default}.form-el-radio:checked+.form-label:after{border-color:#514943}.form-select-label{border:1px solid #adadad;border-radius:2px;color:#303030;cursor:pointer;display:block;overflow:hidden;position:relative}.form-select-label:hover,.form-select-label:hover:after{border-color:#949494}.form-select-label:active,.form-select-label:active:after,.form-select-label:focus,.form-select-label:focus:after{border-color:#008bdb}.form-select-label:after{background:#e3e3e3;border-left:1px solid #adadad;bottom:0;content:'';position:absolute;right:0;top:0;width:2.36em;z-index:-2}.ie9 .form-select-label:after{display:none}.form-select-label:before{border-color:#303030 transparent transparent;border-style:solid;border-width:5px 4px 0;content:'';height:0;margin-right:-4px;margin-top:-2.5px;position:absolute;right:1.18em;top:50%;width:0;z-index:-1}.ie9 .form-select-label:before{display:none}.form-select-label .form-el-select{background:0 0;border:none;border-radius:0;content:'';display:block;margin:0;padding:.35em calc(2.36em + 10%) .5em .55em;width:110%}.ie9 .form-select-label .form-el-select{padding-right:.55em;width:100%}.form-el-select{background:#fff;border:1px solid #adadad;border-radius:2px;color:#303030;display:block;padding:.35em .55em}.multiselect-custom{position:relative;height:45.2rem;border:1px solid #adadad;overflow:auto;margin:0 0 1.5rem}.multiselect-custom ul{margin:0;padding:0;list-style:none;min-width:29rem}.multiselect-custom .item{padding:1rem 1.4rem}.multiselect-custom .selected{background-color:#e0f6fe}.multiselect-custom .form-label{margin-bottom:0}[class*=form-el-].invalid{border-color:#e22626}[class*=form-el-].invalid+.error-container{display:block}.error-container{background-color:#fffbbb;border:1px solid #ee7d7d;border-radius:2px;color:#514943;display:none;font-size:1.19rem;margin-top:.2rem;padding:.4235em .6655em .605em}.check-result-message{margin-left:.5em;min-height:3.68rem;-webkit-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.check-result-text{margin-left:.5em}.pseudo-table{display:table}.pseudo-td{display:table-cell}.messages{margin:0 0 2rem}.message{background:#fffbbb;border:none;border-radius:0;color:#333;font-size:14px;margin:0 0 1px;padding:1.8rem 4rem 1.8rem 5.5rem;position:relative;text-shadow:none}.message:before{background:0 0;border:0;color:#007bdb;content:'\e61a';font-family:Icons;font-size:1.9rem;font-style:normal;font-weight:400;height:auto;left:1.9rem;line-height:inherit;margin-top:-1.3rem;position:absolute;speak:none;text-shadow:none;top:50%;width:auto}.message-notice:before{color:#007bdb;content:'\e61a'}.message-warning:before{color:#eb5202;content:'\e623'}.message-error{background:#fcc}.message-error:before{color:#e22626;content:'\e632';font-size:1.5rem;left:2.2rem;margin-top:-1rem}.message-success:before{color:#79a22e;content:'\e62d'}.message-spinner:before{display:none}.message-spinner .spinner{font-size:2.5rem;left:1.5rem;position:absolute;top:1.5rem}.message-in-rating-edit{margin-left:1.8rem;margin-right:1.8rem}.message{margin-bottom:3rem}.container{display:block;margin:0 auto 4rem;max-width:100rem;padding:0 2rem}.row{margin-left:0;margin-right:0}.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9,.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{min-height:1px;padding-left:0;padding-right:0;position:relative}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}.nav{background-color:#f8f8f8;border-bottom:1px solid #e3e3e3;border-top:1px solid #e3e3e3;display:none;padding:2.2rem 1.5rem 0 0}.nav .btn-group,.nav-bar-outer-actions{float:right;margin-bottom:1.7rem}.nav .btn-group .btn-wrap,.nav-bar-outer-actions .btn-wrap{float:right;margin-left:.5rem;margin-right:.5rem}.nav-bar-outer-actions{margin-top:-10.6rem;padding-right:1.5rem}.btn-wrap-try-again{width:9.5rem}.btn-wrap-next,.btn-wrap-prev{width:8.5rem}.nav-bar{counter-reset:i;float:left;margin:0 1rem 1.7rem 0;padding:0;position:relative;white-space:nowrap}.nav-bar:before{background-color:#d4d4d4;background-repeat:repeat-x;background-image:linear-gradient(to bottom,#d1d1d1 0,#d4d4d4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d1d1d1', endColorstr='#d4d4d4', GradientType=0);border-bottom:1px solid #d9d9d9;border-top:1px solid #bfbfbf;content:'';height:.8rem;left:5.15rem;position:absolute;right:5.15rem;top:.7rem}.nav-bar>li{display:inline-block;font-size:0;position:relative;vertical-align:top;width:10.3rem}.nav-bar>li:first-child:after{display:none}.nav-bar>li:after{background-color:#514943;content:'';height:.5rem;left:calc(-50% + .25rem);position:absolute;right:calc(50% + .7rem);top:.9rem}.nav-bar>li.disabled:before{bottom:0;content:'';left:0;position:absolute;right:0;top:0;z-index:1}.nav-bar>li.active~li:after{display:none}.nav-bar>li.active~li a:after{background-color:transparent;border-color:transparent;color:#a6a6a6}.nav-bar>li.active a{color:#000}.nav-bar>li.active a:hover{cursor:default}.nav-bar>li.active a:after{background-color:#fff;content:''}.nav-bar a{color:#514943;display:block;font-size:1.2rem;font-weight:600;line-height:1.2;overflow:hidden;padding:3rem .5em 0;position:relative;text-align:center;text-overflow:ellipsis}.nav-bar a:hover{text-decoration:none}.nav-bar a:after{background-color:#514943;border:.4rem solid #514943;border-radius:100%;color:#fff;content:counter(i);counter-increment:i;height:.7rem;left:50%;line-height:.6;margin-left:-.8rem;position:absolute;right:auto;text-align:center;top:.4rem;width:.7rem}.nav-bar a:before{background-color:#d6d6d6;border:1px solid transparent;border-bottom-color:#d9d9d9;border-radius:100%;border-top-color:#bfbfbf;content:'';height:2.1rem;left:50%;line-height:1;margin-left:-1.2rem;position:absolute;top:0;width:2.1rem}.tooltip{display:block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.19rem;font-weight:400;line-height:1.4;opacity:0;position:absolute;visibility:visible;z-index:10}.tooltip.in{opacity:.9}.tooltip.top{margin-top:-4px;padding:8px 0}.tooltip.right{margin-left:4px;padding:0 8px}.tooltip.bottom{margin-top:4px;padding:8px 0}.tooltip.left{margin-left:-4px;padding:0 8px}.tooltip-inner{background-color:#fff;border:1px solid #adadad;border-radius:0;box-shadow:1px 1px 1px #ccc;color:#41362f;max-width:20rem;padding:.5em 1em;text-decoration:none}.tooltip-arrow,.tooltip-arrow:after{border:solid transparent;height:0;position:absolute;width:0}.tooltip-arrow:after{content:'';position:absolute}.tooltip.top .tooltip-arrow,.tooltip.top .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:50%;margin-left:-8px}.tooltip.top-left .tooltip-arrow,.tooltip.top-left .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;margin-bottom:-8px;right:8px}.tooltip.top-right .tooltip-arrow,.tooltip.top-right .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:8px;margin-bottom:-8px}.tooltip.right .tooltip-arrow,.tooltip.right .tooltip-arrow:after{border-right-color:#949494;border-width:8px 8px 8px 0;left:1px;margin-top:-8px;top:50%}.tooltip.right .tooltip-arrow:after{border-right-color:#fff;border-width:6px 7px 6px 0;margin-left:0;margin-top:-6px}.tooltip.left .tooltip-arrow,.tooltip.left .tooltip-arrow:after{border-left-color:#949494;border-width:8px 0 8px 8px;margin-top:-8px;right:0;top:50%}.tooltip.bottom .tooltip-arrow,.tooltip.bottom .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:50%;margin-left:-8px;top:0}.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;margin-top:-8px;right:8px;top:0}.tooltip.bottom-right .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:8px;margin-top:-8px;top:0}.password-strength{display:block;margin:0 -.3rem 1em;white-space:nowrap}.password-strength.password-strength-too-short .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child+.password-strength-item{background-color:#e22626}.password-strength.password-strength-fair .password-strength-item:first-child,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item+.password-strength-item{background-color:#ef672f}.password-strength.password-strength-good .password-strength-item:first-child,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item+.password-strength-item,.password-strength.password-strength-strong .password-strength-item{background-color:#79a22e}.password-strength .password-strength-item{background-color:#ccc;display:inline-block;font-size:0;height:1.4rem;margin-right:.3rem;width:calc(20% - .6rem)}@-webkit-keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}.progress{background-color:#fafafa;border:1px solid #ccc;height:3rem;margin-bottom:3rem;overflow:hidden}.progress-bar{background-color:#79a22e;color:#fff;float:left;font-size:1.19rem;height:100%;line-height:3rem;text-align:center;transition:width .6s ease;width:0}.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.spinner{display:inline-block;font-size:4rem;height:1em;margin-right:1.5rem;position:relative;width:1em}@-webkit-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}.spinner>span:nth-child(1){-webkit-animation-delay:.27s;animation-delay:.27s;-webkit-transform:rotate(-315deg);-ms-transform:rotate(-315deg);transform:rotate(-315deg)}.spinner>span:nth-child(2){-webkit-animation-delay:.36s;animation-delay:.36s;-webkit-transform:rotate(-270deg);-ms-transform:rotate(-270deg);transform:rotate(-270deg)}.spinner>span:nth-child(3){-webkit-animation-delay:.45s;animation-delay:.45s;-webkit-transform:rotate(-225deg);-ms-transform:rotate(-225deg);transform:rotate(-225deg)}.spinner>span:nth-child(4){-webkit-animation-delay:.54s;animation-delay:.54s;-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.spinner>span:nth-child(5){-webkit-animation-delay:.63s;animation-delay:.63s;-webkit-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.spinner>span:nth-child(6){-webkit-animation-delay:.72s;animation-delay:.72s;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.spinner>span:nth-child(7){-webkit-animation-delay:.81s;animation-delay:.81s;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.spinner>span:nth-child(8){-webkit-animation-delay:.9;animation-delay:.9;-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}.spinner>span{-webkit-animation-direction:linear;animation-direction:linear;-webkit-animation-duration:.72s;animation-duration:.72s;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fade;animation-name:fade;-webkit-transform:scale(0.4);-ms-transform:scale(0.4);transform:scale(0.4);background-color:#fff;border-radius:6px;clip:rect(0 .28571429em .1em 0);height:.1em;margin-top:.5em;position:absolute;width:1em}.ie9 .spinner{background:url(../../pub/images/ajax-loader.gif) center no-repeat}.ie9 .spinner>span{display:none}.main{padding-bottom:2rem;padding-top:3rem}.header{display:none}.header .logo{float:left;height:4.1rem;width:3.5rem}.header-title{font-size:2.8rem;letter-spacing:.02em;margin:2.5rem 0 3.5rem 5rem}.page-title{font-size:2rem;margin-bottom:1.3em}.accent-box{margin-bottom:2rem}.accent-box .btn-prime{margin-top:1.5rem}.page-landing{margin:7.6% auto 0;max-width:44rem;text-align:center}.page-landing .logo{height:5.6rem;margin-bottom:2rem;width:19.2rem}.page-landing .text-version{margin-bottom:3rem}.page-landing .text-welcome{margin-bottom:6.5rem}.page-landing .text-terms{margin-bottom:2.5rem;text-align:center}.page-landing .btn-submit{margin-bottom:20px}.page-license .license-text{margin-bottom:2rem}.page-license .page-license-footer{text-align:right}.rediness-check-item{margin-bottom:4rem}.readiness-check-title{font-size:1.4rem;font-weight:700;margin-bottom:.1rem;margin-left:7.5rem}.readiness-check-content{margin-left:7.5rem;margin-right:22rem}.readiness-check-content .readiness-check-title{margin-left:0}.readiness-check-content .list{margin-top:-.3rem}.rediness-check-side{float:right;padding-left:2.4rem;width:22rem}.rediness-check-side .side-title{margin-bottom:0}.readiness-check-icon{float:left;margin-left:2rem;margin-top:.7rem}.page-web-configuration .form-el-insider-wrap{width:auto}.page-web-configuration .form-el-insider{width:15.4rem}.page-web-configuration .form-el-insider-input .form-el-input{width:16.5rem}.customize-your-store .customize-your-store-default .legend{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.customize-your-store .advanced-modules-count,.customize-your-store .advanced-modules-select{padding-left:1.5rem}.customize-your-store .customize-your-store-advanced{min-width:0}.customize-your-store .message-error:before{margin-top:0;top:1.8rem}.customize-your-store .message-error a{color:#333;text-decoration:underline}.customize-your-store .message-error .form-label:before{background:#fff}.content-install{margin-bottom:2rem}.console{border:1px solid #ccc;font-family:'Courier New',Courier,monospace;font-weight:300;margin:1rem 0 2rem;max-height:20rem;overflow-y:auto;padding:1.5rem 2rem 2rem}.console .text-danger{color:#e22626}.console .text-success{color:#090}.console .hidden{display:none}.content-success .btn-prime{margin-top:1.5rem}.jumbo-title{font-size:3.6rem}.jumbo-title .jumbo-icon{font-size:3.8rem;margin-right:.25em;position:relative;top:.15em}@media all and (max-width:1047px){.nav{padding-bottom:5.38rem;padding-left:1.5rem;text-align:center}.nav-bar{display:inline-block;float:none;margin-right:0;vertical-align:top}.nav .btn-group,.nav-bar-outer-actions{display:inline-block;float:none;margin-top:-8.48rem;text-align:center;vertical-align:top;width:100%}.nav-bar-outer-actions{padding-right:0}.nav-bar-outer-actions .outer-actions-inner-wrap{display:inline-block}}@media all and (min-width:768px){.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9{float:left}.col-m-12{width:100%}.col-m-11{width:91.66666667%}.col-m-10{width:83.33333333%}.col-m-9{width:75%}.col-m-8{width:66.66666667%}.col-m-7{width:58.33333333%}.col-m-6{width:50%}.col-m-5{width:41.66666667%}.col-m-4{width:33.33333333%}.col-m-3{width:25%}.col-m-2{width:16.66666667%}.col-m-1{width:8.33333333%}.col-m-pull-12{right:100%}.col-m-pull-11{right:91.66666667%}.col-m-pull-10{right:83.33333333%}.col-m-pull-9{right:75%}.col-m-pull-8{right:66.66666667%}.col-m-pull-7{right:58.33333333%}.col-m-pull-6{right:50%}.col-m-pull-5{right:41.66666667%}.col-m-pull-4{right:33.33333333%}.col-m-pull-3{right:25%}.col-m-pull-2{right:16.66666667%}.col-m-pull-1{right:8.33333333%}.col-m-pull-0{right:auto}.col-m-push-12{left:100%}.col-m-push-11{left:91.66666667%}.col-m-push-10{left:83.33333333%}.col-m-push-9{left:75%}.col-m-push-8{left:66.66666667%}.col-m-push-7{left:58.33333333%}.col-m-push-6{left:50%}.col-m-push-5{left:41.66666667%}.col-m-push-4{left:33.33333333%}.col-m-push-3{left:25%}.col-m-push-2{left:16.66666667%}.col-m-push-1{left:8.33333333%}.col-m-push-0{left:auto}.col-m-offset-12{margin-left:100%}.col-m-offset-11{margin-left:91.66666667%}.col-m-offset-10{margin-left:83.33333333%}.col-m-offset-9{margin-left:75%}.col-m-offset-8{margin-left:66.66666667%}.col-m-offset-7{margin-left:58.33333333%}.col-m-offset-6{margin-left:50%}.col-m-offset-5{margin-left:41.66666667%}.col-m-offset-4{margin-left:33.33333333%}.col-m-offset-3{margin-left:25%}.col-m-offset-2{margin-left:16.66666667%}.col-m-offset-1{margin-left:8.33333333%}.col-m-offset-0{margin-left:0}}@media all and (min-width:1048px){.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9{float:left}.col-l-12{width:100%}.col-l-11{width:91.66666667%}.col-l-10{width:83.33333333%}.col-l-9{width:75%}.col-l-8{width:66.66666667%}.col-l-7{width:58.33333333%}.col-l-6{width:50%}.col-l-5{width:41.66666667%}.col-l-4{width:33.33333333%}.col-l-3{width:25%}.col-l-2{width:16.66666667%}.col-l-1{width:8.33333333%}.col-l-pull-12{right:100%}.col-l-pull-11{right:91.66666667%}.col-l-pull-10{right:83.33333333%}.col-l-pull-9{right:75%}.col-l-pull-8{right:66.66666667%}.col-l-pull-7{right:58.33333333%}.col-l-pull-6{right:50%}.col-l-pull-5{right:41.66666667%}.col-l-pull-4{right:33.33333333%}.col-l-pull-3{right:25%}.col-l-pull-2{right:16.66666667%}.col-l-pull-1{right:8.33333333%}.col-l-pull-0{right:auto}.col-l-push-12{left:100%}.col-l-push-11{left:91.66666667%}.col-l-push-10{left:83.33333333%}.col-l-push-9{left:75%}.col-l-push-8{left:66.66666667%}.col-l-push-7{left:58.33333333%}.col-l-push-6{left:50%}.col-l-push-5{left:41.66666667%}.col-l-push-4{left:33.33333333%}.col-l-push-3{left:25%}.col-l-push-2{left:16.66666667%}.col-l-push-1{left:8.33333333%}.col-l-push-0{left:auto}.col-l-offset-12{margin-left:100%}.col-l-offset-11{margin-left:91.66666667%}.col-l-offset-10{margin-left:83.33333333%}.col-l-offset-9{margin-left:75%}.col-l-offset-8{margin-left:66.66666667%}.col-l-offset-7{margin-left:58.33333333%}.col-l-offset-6{margin-left:50%}.col-l-offset-5{margin-left:41.66666667%}.col-l-offset-4{margin-left:33.33333333%}.col-l-offset-3{margin-left:25%}.col-l-offset-2{margin-left:16.66666667%}.col-l-offset-1{margin-left:8.33333333%}.col-l-offset-0{margin-left:0}}@media all and (min-width:1440px){.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{float:left}.col-xl-12{width:100%}.col-xl-11{width:91.66666667%}.col-xl-10{width:83.33333333%}.col-xl-9{width:75%}.col-xl-8{width:66.66666667%}.col-xl-7{width:58.33333333%}.col-xl-6{width:50%}.col-xl-5{width:41.66666667%}.col-xl-4{width:33.33333333%}.col-xl-3{width:25%}.col-xl-2{width:16.66666667%}.col-xl-1{width:8.33333333%}.col-xl-pull-12{right:100%}.col-xl-pull-11{right:91.66666667%}.col-xl-pull-10{right:83.33333333%}.col-xl-pull-9{right:75%}.col-xl-pull-8{right:66.66666667%}.col-xl-pull-7{right:58.33333333%}.col-xl-pull-6{right:50%}.col-xl-pull-5{right:41.66666667%}.col-xl-pull-4{right:33.33333333%}.col-xl-pull-3{right:25%}.col-xl-pull-2{right:16.66666667%}.col-xl-pull-1{right:8.33333333%}.col-xl-pull-0{right:auto}.col-xl-push-12{left:100%}.col-xl-push-11{left:91.66666667%}.col-xl-push-10{left:83.33333333%}.col-xl-push-9{left:75%}.col-xl-push-8{left:66.66666667%}.col-xl-push-7{left:58.33333333%}.col-xl-push-6{left:50%}.col-xl-push-5{left:41.66666667%}.col-xl-push-4{left:33.33333333%}.col-xl-push-3{left:25%}.col-xl-push-2{left:16.66666667%}.col-xl-push-1{left:8.33333333%}.col-xl-push-0{left:auto}.col-xl-offset-12{margin-left:100%}.col-xl-offset-11{margin-left:91.66666667%}.col-xl-offset-10{margin-left:83.33333333%}.col-xl-offset-9{margin-left:75%}.col-xl-offset-8{margin-left:66.66666667%}.col-xl-offset-7{margin-left:58.33333333%}.col-xl-offset-6{margin-left:50%}.col-xl-offset-5{margin-left:41.66666667%}.col-xl-offset-4{margin-left:33.33333333%}.col-xl-offset-3{margin-left:25%}.col-xl-offset-2{margin-left:16.66666667%}.col-xl-offset-1{margin-left:8.33333333%}.col-xl-offset-0{margin-left:0}}@media all and (max-width:767px){.list-definition>dt{float:none}.list-definition>dd{margin-left:0}.form-row .form-label{text-align:left}.form-row .form-label.required:after{position:static}.nav{padding-bottom:0;padding-left:0;padding-right:0}.nav-bar-outer-actions{margin-top:0}.nav-bar{display:block;margin-bottom:0;margin-left:auto;margin-right:auto;width:30.9rem}.nav-bar:before{display:none}.nav-bar>li{float:left;min-height:9rem}.nav-bar>li:after{display:none}.nav-bar>li:nth-child(4n){clear:both}.nav-bar a{line-height:1.4}.tooltip{display:none!important}.readiness-check-content{margin-right:2rem}.form-el-insider,.form-el-insider-wrap,.page-web-configuration .form-el-insider-input,.page-web-configuration .form-el-insider-input .form-el-input{display:block;width:100%}}@media all and (max-width:479px){.nav-bar{width:23.175rem}.nav-bar>li{width:7.725rem}.nav .btn-group .btn-wrap-try-again,.nav-bar-outer-actions .btn-wrap-try-again{clear:both;display:block;float:none;margin-left:auto;margin-right:auto;margin-top:1rem;padding-top:1rem}} \ No newline at end of file diff --git a/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php b/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php index 3b8975c02de354a3b9f94cd8763ce934429a4559..7803cacfed564b1b2a75329bb22eaa9610fedb3e 100644 --- a/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php +++ b/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php @@ -11,7 +11,7 @@ use Symfony\Component\Console\Input\InputOption; /** * An abstract class for all Magento Setup command. - * It adds InitParamListener's magento_init_params option to all setup command. + * It adds InitParamListener's magento-init-params option to all setup command. */ abstract class AbstractSetupCommand extends Command { diff --git a/setup/src/Magento/Setup/Console/Command/InstallCommand.php b/setup/src/Magento/Setup/Console/Command/InstallCommand.php index 2601e45b7aa1e5eb9fa960670e7055e7c9ce433f..d4dbcc4e44acab019cbb0a16750d3605a32687e3 100644 --- a/setup/src/Magento/Setup/Console/Command/InstallCommand.php +++ b/setup/src/Magento/Setup/Console/Command/InstallCommand.php @@ -14,23 +14,24 @@ use Magento\Setup\Model\ConfigModel; /** * Command to install Magento application + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class InstallCommand extends AbstractSetupCommand { /** * Parameter indicating command whether to cleanup database in the install routine */ - const INPUT_KEY_CLEANUP_DB = 'cleanup_database'; + const INPUT_KEY_CLEANUP_DB = 'cleanup-database'; /** * Parameter to specify an order_increment_prefix */ - const INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX = 'sales_order_increment_prefix'; + const INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX = 'sales-order-increment-prefix'; /** * Parameter indicating command whether to install Sample Data */ - const INPUT_KEY_USE_SAMPLE_DATA = 'use_sample_data'; + const INPUT_KEY_USE_SAMPLE_DATA = 'use-sample-data'; /** * Installer service factory diff --git a/setup/src/Magento/Setup/Fixtures/CartPriceRulesFixture.php b/setup/src/Magento/Setup/Fixtures/CartPriceRulesFixture.php index b5d18c63d122fb8100f6b75413e9b606ece384e4..08373f57ea5d648c1e0e0554d141642387f0e06d 100644 --- a/setup/src/Magento/Setup/Fixtures/CartPriceRulesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CartPriceRulesFixture.php @@ -22,8 +22,14 @@ class CartPriceRulesFixture extends Fixture public function execute() { $this->fixtureModel->resetObjectManager(); - $cartPriceRulesCount = $this->fixtureModel->getValue('cart_price_rules', 9); - $cartPriceRulesProductsFloor = $this->fixtureModel->getValue('cart_price_rules_floor', 3); + $cartPriceRulesCount = $this->fixtureModel->getValue('cart_price_rules', 0); + if (!$cartPriceRulesCount) { + return; + } + $cartPriceRulesProductsFloor = $this->fixtureModel->getValue( + 'cart_price_rules_floor', + 3 + ); /** @var \Magento\Store\Model\StoreManager $storeManager */ $storeManager = $this->fixtureModel->getObjectManager()->create('Magento\Store\Model\StoreManager'); diff --git a/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php b/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php index 4a33e4a3cded0014982c93868ff8486c0dfd604f..fef1b761bcb3019f46e1c4669fec3ba71867bdbc 100644 --- a/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php @@ -21,7 +21,10 @@ class CatalogPriceRulesFixture extends Fixture */ public function execute() { - $catalogPriceRulesCount = $this->fixtureModel->getValue('catalog_price_rules', 3); + $catalogPriceRulesCount = $this->fixtureModel->getValue('catalog_price_rules', 0); + if (!$catalogPriceRulesCount) { + return; + } $this->fixtureModel->resetObjectManager(); /** @var \Magento\Store\Model\StoreManager $storeManager */ diff --git a/setup/src/Magento/Setup/Fixtures/CategoriesFixture.php b/setup/src/Magento/Setup/Fixtures/CategoriesFixture.php index 9cbba51d1bef73f923a966b2319b11b8f79cb98e..7a512d026757df6caed19e77e5cc1af1a759d8b9 100644 --- a/setup/src/Magento/Setup/Fixtures/CategoriesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CategoriesFixture.php @@ -21,7 +21,10 @@ class CategoriesFixture extends Fixture */ public function execute() { - $categoriesNumber = $this->fixtureModel->getValue('categories', 18); + $categoriesNumber = $this->fixtureModel->getValue('categories', 0); + if (!$categoriesNumber) { + return; + } $maxNestingLevel = $this->fixtureModel->getValue('categories_nesting_level', 3); $this->fixtureModel->resetObjectManager(); diff --git a/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php index d69e54d3851f12f0d3d9f4ca69efe9051eb8016b..a4cb005c76a0588fd78abaa9254789f6ea6295a9 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php @@ -22,6 +22,9 @@ class ConfigsApplyFixture extends Fixture public function execute() { $configs = $this->fixtureModel->getValue('configs', array()); + if (empty($configs)) { + return; + } $this->fixtureModel->resetObjectManager(); foreach ($configs['config'] as $config) { diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 73af579e0fc84f513391aed8b45bc45e56a90f8f..2d0f51e7cdc4b40bd1072a7b35d0023b7a18f5a3 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -825,7 +825,10 @@ class ConfigurableProductsFixture extends Fixture */ public function execute() { - $configurablesCount = $this->fixtureModel->getValue('configurable_products', 90); + $configurablesCount = $this->fixtureModel->getValue('configurable_products', 0); + if (!$configurablesCount) { + return; + } $this->fixtureModel->resetObjectManager(); /** @var \Magento\Store\Model\StoreManager $storeManager */ diff --git a/setup/src/Magento/Setup/Fixtures/CustomersFixture.php b/setup/src/Magento/Setup/Fixtures/CustomersFixture.php index e1f7c7e7cf0c2fde7664c544fd178453b8101ae6..e96460fffa2549b7de3c8291df4b8c65856139d8 100644 --- a/setup/src/Magento/Setup/Fixtures/CustomersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/CustomersFixture.php @@ -23,7 +23,10 @@ class CustomersFixture extends Fixture */ public function execute() { - $customersNumber = $this->fixtureModel->getValue('customers', 10); + $customersNumber = $this->fixtureModel->getValue('customers', 0); + if (!$customersNumber) { + return; + } $this->fixtureModel->resetObjectManager(); /** @var \Magento\Store\Model\StoreManager $storeManager */ diff --git a/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php b/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php index b06da8f8612128b9c7bffac264d5838fa5dae664..e6baa1aabfb141d6daaa94dd766f8cc1ee4c3d10 100644 --- a/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php @@ -23,6 +23,10 @@ class EavVariationsFixture extends Fixture */ public function execute() { + $configurablesCount = $this->fixtureModel->getValue('configurable_products', 0); + if (!$configurablesCount) { + return; + } $this->fixtureModel->resetObjectManager(); /* @var $model \Magento\Catalog\Model\Resource\Eav\Attribute */ diff --git a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php index ef1f39419151dbfd0d339fe96e90e159d30a30b8..56e255e87eabf52b85bb850a314c71fb9aba50eb 100644 --- a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php @@ -23,7 +23,10 @@ class SimpleProductsFixture extends Fixture */ public function execute() { - $simpleProductsCount = $this->fixtureModel->getValue('simple_products', 180); + $simpleProductsCount = $this->fixtureModel->getValue('simple_products', 0); + if (!$simpleProductsCount) { + return; + } $this->fixtureModel->resetObjectManager(); /** @var \Magento\Store\Model\StoreManager $storeManager */ diff --git a/setup/src/Magento/Setup/Fixtures/StoresFixture.php b/setup/src/Magento/Setup/Fixtures/StoresFixture.php index 0a8a6c1fa77a17a30be8ecd0c663120f0338de57..da9186baeae3583dac213aa5c8e400a8e32ae0d3 100644 --- a/setup/src/Magento/Setup/Fixtures/StoresFixture.php +++ b/setup/src/Magento/Setup/Fixtures/StoresFixture.php @@ -21,9 +21,12 @@ class StoresFixture extends Fixture */ public function execute() { - $websitesCount = $this->fixtureModel->getValue('websites', 2); - $storeGroupsCount = $this->fixtureModel->getValue('store_groups', 3); - $storesCount = $this->fixtureModel->getValue('store_views', 5); + $websitesCount = $this->fixtureModel->getValue('websites', 0); + $storeGroupsCount = $this->fixtureModel->getValue('store_groups', 0); + $storesCount = $this->fixtureModel->getValue('store_views', 0); + if (!$websitesCount || !$storeGroupsCount || !$storesCount) { + return; + } $this->fixtureModel->resetObjectManager(); /** @var \Magento\Store\Model\StoreManager $storeManager */ diff --git a/setup/src/Magento/Setup/Fixtures/TaxRatesFixture.php b/setup/src/Magento/Setup/Fixtures/TaxRatesFixture.php index 9380f683369d092b46c69baff6a1041216b5414d..818da63a4ceacdff3267b58101430700bfc42ff7 100644 --- a/setup/src/Magento/Setup/Fixtures/TaxRatesFixture.php +++ b/setup/src/Magento/Setup/Fixtures/TaxRatesFixture.php @@ -21,6 +21,10 @@ class TaxRatesFixture extends Fixture */ public function execute() { + $taxRatesFile = $this->fixtureModel->getValue('tax_rates_file', null); + if (empty($taxRatesFile)) { + return; + } $this->fixtureModel->resetObjectManager(); /** Clean predefined tax rates to maintain consistency */ /** @var $collection Magento\Tax\Model\Resource\Calculation\Rate\Collection */ @@ -38,7 +42,7 @@ class TaxRatesFixture extends Fixture /** * Import tax rates with import handler */ - $filename = realpath(__DIR__ . '/tax_rates.csv'); + $filename = realpath(__DIR__ . '/' . $taxRatesFile); $file = [ 'name' => $filename, 'type' => 'fixtureModel/vnd.ms-excel', diff --git a/setup/src/Magento/Setup/Model/AdminAccount.php b/setup/src/Magento/Setup/Model/AdminAccount.php index 7e52b2b604e10f76f660e28d50f26cf59f3d2c6e..5642dda6afb31035d259682e06f7cb078a01cd16 100644 --- a/setup/src/Magento/Setup/Model/AdminAccount.php +++ b/setup/src/Magento/Setup/Model/AdminAccount.php @@ -17,11 +17,11 @@ class AdminAccount /**#@+ * Data keys */ - const KEY_USER = 'admin_user'; - const KEY_PASSWORD = 'admin_password'; - const KEY_EMAIL = 'admin_email'; - const KEY_FIRST_NAME = 'admin_firstname'; - const KEY_LAST_NAME = 'admin_lastname'; + const KEY_USER = 'admin-user'; + const KEY_PASSWORD = 'admin-password'; + const KEY_EMAIL = 'admin-email'; + const KEY_FIRST_NAME = 'admin-firstname'; + const KEY_LAST_NAME = 'admin-lastname'; /**#@- */ /** diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 5db3a546a66113ea49ff556c9f346281ec8afc44..414ef89f37a612ce5dcbbe14f6438d30e11a11a5 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -787,6 +787,9 @@ class Installer public function installUserConfig($data) { $userConfig = new StoreConfigurationDataMapper(); + /** @var \Magento\Framework\App\State $appState */ + $appState = $this->objectManagerProvider->get()->get('Magento\Framework\App\State'); + $appState->setAreaCode('setup'); $configData = $userConfig->getConfigData($data); if (count($configData) === 0) { return; diff --git a/setup/src/Magento/Setup/Model/Lists.php b/setup/src/Magento/Setup/Model/Lists.php index e898ed40c16c383ac2fa1ccadbdab2419aae793d..e52e921594caec60421e975f3782c8abf552ac13 100644 --- a/setup/src/Magento/Setup/Model/Lists.php +++ b/setup/src/Magento/Setup/Model/Lists.php @@ -10,6 +10,7 @@ use Magento\Framework\Locale\Bundle\CurrencyBundle; use Magento\Framework\Locale\Bundle\LanguageBundle; use Magento\Framework\Locale\Bundle\RegionBundle; use Magento\Framework\Locale\ConfigInterface; +use Magento\Framework\Locale\Resolver; use Magento\Framework\Locale\ResolverInterface; class Lists @@ -42,7 +43,7 @@ class Lists $list[$code] = \IntlTimeZone::createTimeZone($code)->getDisplayName( false, \IntlTimeZone::DISPLAY_LONG, - ResolverInterface::DEFAULT_LOCALE + Resolver::DEFAULT_LOCALE ) . ' (' . $code . ')'; } asort($list); @@ -56,7 +57,7 @@ class Lists */ public function getCurrencyList() { - $currencies = (new CurrencyBundle())->get(ResolverInterface::DEFAULT_LOCALE)['Currencies']; + $currencies = (new CurrencyBundle())->get(Resolver::DEFAULT_LOCALE)['Currencies']; $list = []; foreach ($currencies as $code => $data) { $list[$code] = $data[1] . ' (' . $code . ')'; @@ -72,8 +73,8 @@ class Lists */ public function getLocaleList() { - $languages = (new LanguageBundle())->get(ResolverInterface::DEFAULT_LOCALE)['Languages']; - $countries = (new RegionBundle())->get(ResolverInterface::DEFAULT_LOCALE)['Countries']; + $languages = (new LanguageBundle())->get(Resolver::DEFAULT_LOCALE)['Languages']; + $countries = (new RegionBundle())->get(Resolver::DEFAULT_LOCALE)['Countries']; $locales = \ResourceBundle::getLocales(null); $list = []; diff --git a/setup/src/Magento/Setup/Model/StoreConfigurationDataMapper.php b/setup/src/Magento/Setup/Model/StoreConfigurationDataMapper.php index 0fa3c235244568c8a4e7dbf2595c658f87f9dd68..11a3a36e4cd388bb959d79368456f8927f1eeb4c 100644 --- a/setup/src/Magento/Setup/Model/StoreConfigurationDataMapper.php +++ b/setup/src/Magento/Setup/Model/StoreConfigurationDataMapper.php @@ -22,15 +22,15 @@ class StoreConfigurationDataMapper /**#@+ * Model data keys */ - const KEY_USE_SEF_URL = 'use_rewrites'; - const KEY_BASE_URL = 'base_url'; - const KEY_BASE_URL_SECURE = 'base_url_secure'; - const KEY_IS_SECURE = 'use_secure'; - const KEY_IS_SECURE_ADMIN = 'use_secure_admin'; + const KEY_USE_SEF_URL = 'use-rewrites'; + const KEY_BASE_URL = 'base-url'; + const KEY_BASE_URL_SECURE = 'base-url-secure'; + const KEY_IS_SECURE = 'use-secure'; + const KEY_IS_SECURE_ADMIN = 'use-secure-admin'; const KEY_LANGUAGE = 'language'; const KEY_TIMEZONE = 'timezone'; const KEY_CURRENCY = 'currency'; - const KEY_ADMIN_USE_SECURITY_KEY = 'admin_use_security_key'; + const KEY_ADMIN_USE_SECURITY_KEY = 'admin-use-security-key'; /**#@- */ /** diff --git a/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php b/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php index 8ed6beabb634b09230338d7a570a5c6baa0093cc..bbc0cecfa9ce6de7bc74c7fae3dd45acf35f8cc7 100644 --- a/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php +++ b/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php @@ -100,7 +100,7 @@ class Generator /** @var \Magento\Setup\Module\I18n\Dictionary\Phrase $phrase */ $phrase = $phrases[0]; $error .= sprintf( - "The phrase \"%s\" is translated differently in %d places.\n", + "The phrase \"%s\" is translated in %d places.\n", $phrase->getPhrase(), count($phrases) ); diff --git a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php index 1d229e825f9c8f43c165e93bf62574ea9b34c0af..e2525c9e4fbe10e2d3a10fa56372d3bb02d86687 100644 --- a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php +++ b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php @@ -30,7 +30,7 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface /** * A CLI parameter for injecting bootstrap variables */ - const BOOTSTRAP_PARAM = 'magento_init_params'; + const BOOTSTRAP_PARAM = 'magento-init-params'; /** * List of ZF event listeners diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/ConfigSetCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/ConfigSetCommandTest.php index 11e08c4faf7784e8af19f186640dc30ef82b7461..5e7ee9a76a399cea8530457b78a04996861cf2c9 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/ConfigSetCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/ConfigSetCommandTest.php @@ -33,7 +33,7 @@ class ConfigSetCommandTest extends \PHPUnit_Framework_TestCase $option ->expects($this->any()) ->method('getName') - ->will($this->returnValue('db_host')); + ->will($this->returnValue('db-host')); $this->configModel = $this->getMock('Magento\Setup\Model\ConfigModel', [], [], '', false); $this->configModel ->expects($this->exactly(2)) @@ -53,9 +53,9 @@ class ConfigSetCommandTest extends \PHPUnit_Framework_TestCase $this->configModel ->expects($this->once()) ->method('process') - ->with(['db_host' => 'host']); + ->with(['db-host' => 'host']); $commandTester = new CommandTester($this->command); - $commandTester->execute(['--db_host' => 'host']); + $commandTester->execute(['--db-host' => 'host']); $this->assertSame( 'You saved the new configuration.' . PHP_EOL, $commandTester->getDisplay() @@ -71,7 +71,7 @@ class ConfigSetCommandTest extends \PHPUnit_Framework_TestCase $this->configModel ->expects($this->once()) ->method('process') - ->with(['db_host' => 'host']); + ->with(['db-host' => 'host']); $this->checkInteraction(true); } @@ -112,7 +112,7 @@ class ConfigSetCommandTest extends \PHPUnit_Framework_TestCase $this->command->setHelperSet($helperSet); $commandTester = new CommandTester($this->command); - $commandTester->execute(['--db_host' => 'host']); + $commandTester->execute(['--db-host' => 'host']); if ($interactionType) { $message = 'You saved the new configuration.' . PHP_EOL; } else { diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php index 553c5c8ed4c1ec544a824a240237a1b0eb505dca..e3e44ebd20a3b43114e32d7df801c2c86591bf02 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php @@ -234,12 +234,21 @@ class InstallerTest extends \PHPUnit_Framework_TestCase $cacheManager = $this->getMock('Magento\Framework\App\Cache\Manager', [], [], '', false); $cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['foo', 'bar']); $cacheManager->expects($this->once())->method('setEnabled')->willReturn(['foo', 'bar']); + $appState = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( + 'Magento\Framework\App\State' + ); $this->objectManager->expects($this->any()) ->method('create') ->will($this->returnValueMap([ ['Magento\Setup\Module\Setup', ['resource' => $resource], $setup], ['Magento\Setup\Module\DataSetup', [], $dataSetup], ['Magento\Framework\App\Cache\Manager', [], $cacheManager], + ['Magento\Framework\App\State', [], $appState], + ])); + $this->objectManager->expects($this->any()) + ->method('get') + ->will($this->returnValueMap([ + ['Magento\Framework\App\State', $appState], ])); $this->adminFactory->expects($this->once())->method('create')->willReturn( $this->getMock('Magento\Setup\Model\AdminAccount', [], [], '', false) diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php index b8b74152993606d8c1b42535931f5831e67a8de9..0866b50cf75aa2843100f24c9d9be920e510b6c4 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php @@ -110,8 +110,8 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase public function testGenerateWithNotAllowedDuplicatesAndDuplicatesExist() { $error = "Duplicated translation is found, but it is not allowed.\n" - . "The phrase \"phrase1\" is translated differently in 1 places.\n" - . "The phrase \"phrase2\" is translated differently in 1 places.\n"; + . "The phrase \"phrase1\" is translated in 1 places.\n" + . "The phrase \"phrase2\" is translated in 1 places.\n"; $this->setExpectedException('\RuntimeException', $error); $allowDuplicates = false; diff --git a/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php b/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php index 778c734d7e599e59722858d38fa04c110adc3fc5..d0e06963c70effdab4950e340dbb0012f57db37e 100644 --- a/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Mvc/Bootstrap/InitParamListenerTest.php @@ -119,7 +119,7 @@ class InitParamListenerTest extends \PHPUnit_Framework_TestCase $request->expects($this->any()) ->method('getContent') ->willReturn( - $cliParam ? ['install', '--magento_init_params=' . $cliParam ] : ['install'] + $cliParam ? ['install', '--magento-init-params=' . $cliParam ] : ['install'] ); $mvcApplication->expects($this->any())->method('getConfig')->willReturn( $zfAppConfig ? [InitParamListener::BOOTSTRAP_PARAM => $zfAppConfig]:[] diff --git a/setup/view/styles/lib/forms/_checkbox-radio.less b/setup/view/styles/lib/forms/_checkbox-radio.less index 6155541bde86c9f9c1a7111eb63b1bc7d638b4c0..a0510ad6a7c66349c140eefe1745c4e64fcbe3de 100644 --- a/setup/view/styles/lib/forms/_checkbox-radio.less +++ b/setup/view/styles/lib/forms/_checkbox-radio.less @@ -9,7 +9,6 @@ @checkbox__border-color: @color-gray68; @radio-bullet__color: @color-brownie; -@color-required: @color-prime; // // Common @@ -23,7 +22,8 @@ &[disabled], &.disabled { - + .form-label, + .form-label:before { + + .form-label, + + .form-label:before { cursor: default; opacity: @disabled__opacity; pointer-events: none; @@ -31,7 +31,6 @@ } // Hover state - &:not([disabled]), &:not(.disabled) { + .form-label { diff --git a/setup/view/styles/lib/forms/_forms.less b/setup/view/styles/lib/forms/_forms.less index a0e79796f56bbe243d677517531e7222caf0c7be..e0468c4a39b6c5f71bdf67988813b268bb5d1eea 100644 --- a/setup/view/styles/lib/forms/_forms.less +++ b/setup/view/styles/lib/forms/_forms.less @@ -12,6 +12,8 @@ @form-el__focus__border-color: @focus__color; @form-el__hover__border-color: darken(@form-el__border-color, 10%); +@color-required: @color-prime; + // // Structure // _____________________________________________