diff --git a/.htaccess b/.htaccess index 61a6e70d03e7f..89e39655e9289 100644 --- a/.htaccess +++ b/.htaccess @@ -1,213 +1,43 @@ -############################################ -## overrides deployment configuration mode value -## use command bin/magento deploy:mode:set to switch modes - -# SetEnv MAGE_MODE developer - -############################################ -## uncomment these lines for CGI mode -## make sure to specify the correct cgi php binary file name -## it might be /cgi-bin/php-cgi - -# Action php5-cgi /cgi-bin/php5-cgi -# AddHandler php5-cgi .php - -############################################ -## GoDaddy specific options - -# Options -MultiViews - -## you might also need to add this line to php.ini -## cgi.fix_pathinfo = 1 -## if it still doesn't work, rename php.ini to php5.ini - -############################################ -## this line is specific for 1and1 hosting - - #AddType x-mapp-php5 .php - #AddHandler x-mapp-php5 .php - -############################################ -## default index file - - DirectoryIndex index.php - +# All explanations you could find in .htaccess.sample file +DirectoryIndex index.php - -############################################ -## adjust memory limit - php_value memory_limit 768M php_value max_execution_time 18000 - -############################################ -## disable automatic session start -## before autoload was initialized - php_flag session.auto_start off - -############################################ -## enable resulting html compression - - #php_flag zlib.output_compression on - -########################################### -## disable user agent verification to not break multiple image upload - php_flag suhosin.session.cryptua off - - - -############################################ -## adjust memory limit - php_value memory_limit 768M php_value max_execution_time 18000 - -############################################ -## disable automatic session start -## before autoload was initialized - php_flag session.auto_start off - -############################################ -## enable resulting html compression - - #php_flag zlib.output_compression on - -########################################### -## disable user agent verification to not break multiple image upload - php_flag suhosin.session.cryptua off - - -########################################### -## disable POST processing to not break multiple image upload - SecFilterEngine Off SecFilterScanPOST Off - - - -############################################ -## enable apache served files compression -## http://developer.yahoo.com/performance/rules.html#gzip - - # Insert filter on all content - ###SetOutputFilter DEFLATE - # Insert filter on selected content types only - #AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript application/json image/svg+xml - - # Netscape 4.x has some problems... - #BrowserMatch ^Mozilla/4 gzip-only-text/html - - # Netscape 4.06-4.08 have some more problems - #BrowserMatch ^Mozilla/4\.0[678] no-gzip - - # MSIE masquerades as Netscape, but it is fine - #BrowserMatch \bMSIE !no-gzip !gzip-only-text/html - - # Don't compress images - #SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary - - # Make sure proxies don't deliver the wrong content - #Header append Vary User-Agent env=!dont-vary - - - - -############################################ -## make HTTPS env vars available for CGI mode - SSLOptions StdEnvVars - - -############################################ -## workaround for Apache 2.4.6 CentOS build when working via ProxyPassMatch with HHVM (or any other) -## Please, set it on virtual host configuration level - -## SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 -############################################ - - -############################################ -## enable rewrites - Options +FollowSymLinks RewriteEngine on - -############################################ -## you can put here your magento root folder -## path relative to web root - - #RewriteBase /magento/ - -############################################ -## workaround for HTTP authorization -## in CGI environment - RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] - -############################################ -## TRACE and TRACK HTTP methods disabled to prevent XSS attacks - RewriteCond %{REQUEST_METHOD} ^TRAC[EK] RewriteRule .* - [L,R=405] - -############################################ -## redirect for mobile user agents - - #RewriteCond %{REQUEST_URI} !^/mobiledirectoryhere/.*$ - #RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC] - #RewriteRule ^(.*)$ /mobiledirectoryhere/ [L,R=302] - -############################################ -## never rewrite for existing files, directories and links - RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l - -############################################ -## rewrite everything else to index.php - RewriteRule .* index.php [L] - - - -############################################ -## Prevent character encoding issues from server overrides -## If you still have problems, use the second line instead - AddDefaultCharset Off - #AddDefaultCharset UTF-8 AddType 'text/html; charset=UTF-8' html - - -############################################ -## Add default Expires header -## http://developer.yahoo.com/performance/rules.html#expires - ExpiresDefault "access plus 1 year" ExpiresByType text/html A0 ExpiresByType text/plain A0 - - -########################################### -## Deny access to root files to hide sensitive application information RedirectMatch 403 /\.git - order allow,deny deny from all @@ -280,48 +110,11 @@ order allow,deny deny from all - -# For 404s and 403s that aren't handled by the application, show plain 404 response ErrorDocument 404 /pub/errors/404.php ErrorDocument 403 /pub/errors/404.php - -################################ -## If running in cluster environment, uncomment this -## http://developer.yahoo.com/performance/rules.html#etags - - #FileETag none - -# ###################################################################### -# # INTERNET EXPLORER # -# ###################################################################### - -# ---------------------------------------------------------------------- -# | Document modes | -# ---------------------------------------------------------------------- - -# Force Internet Explorer 8/9/10 to render pages in the highest mode -# available in the various cases when it may not. -# -# https://hsivonen.fi/doctype/#ie8 -# -# (!) Starting with Internet Explorer 11, document modes are deprecated. -# If your business still relies on older web apps and services that were -# designed for older versions of Internet Explorer, you might want to -# consider enabling `Enterprise Mode` throughout your company. -# -# https://msdn.microsoft.com/en-us/library/ie/bg182625.aspx#docmode -# http://blogs.msdn.com/b/ie/archive/2014/04/02/stay-up-to-date-with-enterprise-mode-for-internet-explorer-11.aspx - - Header set X-UA-Compatible "IE=edge" - - # `mod_headers` cannot match based on the content-type, however, - # the `X-UA-Compatible` response header should be send only for - # HTML documents and not for the other resources. - Header unset X-UA-Compatible - diff --git a/.htaccess.sample b/.htaccess.sample index 61a6e70d03e7f..85eac7913c73b 100644 --- a/.htaccess.sample +++ b/.htaccess.sample @@ -30,10 +30,9 @@ ############################################ ## default index file - DirectoryIndex index.php +DirectoryIndex index.php - ############################################ ## adjust memory limit @@ -55,11 +54,8 @@ ## disable user agent verification to not break multiple image upload php_flag suhosin.session.cryptua off - - - ############################################ ## adjust memory limit @@ -81,9 +77,7 @@ ## disable user agent verification to not break multiple image upload php_flag suhosin.session.cryptua off - - ########################################### ## disable POST processing to not break multiple image upload diff --git a/.php_cs b/.php_cs index c7f43f02f4fc5..4bd705bb09a2f 100644 --- a/.php_cs +++ b/.php_cs @@ -1,6 +1,6 @@ Apache - PHP 5.6.x, 7.0.2 or 7.0.6 + PHP 5.6.x, 7.0.2, 7.0.4 or 7.0.6 php -v PHP Ubuntu
PHP CentOS diff --git a/app/autoload.php b/app/autoload.php index b817bafa7fa4c..6fdfcd07fdff1 100644 --- a/app/autoload.php +++ b/app/autoload.php @@ -2,7 +2,7 @@ /** * Register basic autoloader that uses include path * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ use Magento\Framework\Autoload\AutoloaderRegistry; diff --git a/app/bootstrap.php b/app/bootstrap.php index 5e693487d748d..eb91654f1fcf4 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -1,6 +1,6 @@ = 50600 && PHP_VERSION_ID < 50700 || PHP_VERSION_ID === 70002 || PHP_VERSION_ID >= 70006)) { +if (!defined('PHP_VERSION_ID') || !(PHP_VERSION_ID >= 50005 && PHP_VERSION_ID < 50700 || PHP_VERSION_ID === 70002 || PHP_VERSION_ID === 70004 || PHP_VERSION_ID >= 70006)) { if (PHP_SAPI == 'cli') { - echo 'Magento supports PHP 5.6, 7.0.2, and 7.0.6 or later. ' . + echo 'Magento supports PHP 5.6.5, 7.0.2, 7.0.4 and 7.0.6 or later. ' . 'Please read http://devdocs.magento.com/guides/v1.0/install-gde/system-requirements.html'; } else { echo << -

Magento supports PHP 5.6, 7.0.2, and 7.0.6 or later. Please read +

Magento supports PHP 5.6.5, 7.0.2, 7.0.4 and 7.0.6 or later. Please read Magento System Requirements. @@ -35,6 +35,17 @@ $mask = file_exists($umaskFile) ? octdec(file_get_contents($umaskFile)) : 002; umask($mask); +if (empty($_SERVER['ENABLE_IIS_REWRITES']) || ($_SERVER['ENABLE_IIS_REWRITES'] != 1)) { + /* + * Unset headers used by IIS URL rewrites. + */ + unset($_SERVER['HTTP_X_REWRITE_URL']); + unset($_SERVER['HTTP_X_ORIGINAL_URL']); + unset($_SERVER['IIS_WasUrlRewritten']); + unset($_SERVER['UNENCODED_URL']); + unset($_SERVER['ORIG_PATH_INFO']); +} + if (!empty($_SERVER['MAGE_PROFILER']) && isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'text/html') !== false diff --git a/app/code/Magento/AdminNotification/Block/Grid/Renderer/Actions.php b/app/code/Magento/AdminNotification/Block/Grid/Renderer/Actions.php index a76f43970ac02..4edf285b3daaa 100644 --- a/app/code/Magento/AdminNotification/Block/Grid/Renderer/Actions.php +++ b/app/code/Magento/AdminNotification/Block/Grid/Renderer/Actions.php @@ -2,7 +2,7 @@ /** * Adminhtml AdminNotification Severity Renderer * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/AdminNotification/Block/Grid/Renderer/Notice.php b/app/code/Magento/AdminNotification/Block/Grid/Renderer/Notice.php index ea065ca1839b2..025bfc18cdc53 100644 --- a/app/code/Magento/AdminNotification/Block/Grid/Renderer/Notice.php +++ b/app/code/Magento/AdminNotification/Block/Grid/Renderer/Notice.php @@ -2,7 +2,7 @@ /** * Adminhtml AdminNotification Severity Renderer * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\AdminNotification\Block\Grid\Renderer; diff --git a/app/code/Magento/AdminNotification/Block/Grid/Renderer/Severity.php b/app/code/Magento/AdminNotification/Block/Grid/Renderer/Severity.php index 7d0ccd163b8e0..c348b6cc76101 100644 --- a/app/code/Magento/AdminNotification/Block/Grid/Renderer/Severity.php +++ b/app/code/Magento/AdminNotification/Block/Grid/Renderer/Severity.php @@ -2,7 +2,7 @@ /** * Adminhtml AdminNotification Severity Renderer * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\AdminNotification\Block\Grid\Renderer; diff --git a/app/code/Magento/AdminNotification/Block/Inbox.php b/app/code/Magento/AdminNotification/Block/Inbox.php index 899d141c9b07f..984de28fd4b94 100644 --- a/app/code/Magento/AdminNotification/Block/Inbox.php +++ b/app/code/Magento/AdminNotification/Block/Inbox.php @@ -2,7 +2,7 @@ /** * Adminhtml AdminNotification inbox grid * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\AdminNotification\Block; diff --git a/app/code/Magento/AdminNotification/Block/System/Messages.php b/app/code/Magento/AdminNotification/Block/System/Messages.php index 223941c6e43f7..db2ecf62f0685 100644 --- a/app/code/Magento/AdminNotification/Block/System/Messages.php +++ b/app/code/Magento/AdminNotification/Block/System/Messages.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/AdminNotification/etc/adminhtml/di.xml b/app/code/Magento/AdminNotification/etc/adminhtml/di.xml index 8986ce73472e5..1be5f99616cc3 100644 --- a/app/code/Magento/AdminNotification/etc/adminhtml/di.xml +++ b/app/code/Magento/AdminNotification/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/etc/adminhtml/events.xml b/app/code/Magento/AdminNotification/etc/adminhtml/events.xml index 07bd1ae5e8e92..9c897af0a2f94 100644 --- a/app/code/Magento/AdminNotification/etc/adminhtml/events.xml +++ b/app/code/Magento/AdminNotification/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/etc/adminhtml/menu.xml b/app/code/Magento/AdminNotification/etc/adminhtml/menu.xml index f64dcbdb51cfd..47c6644b9f369 100644 --- a/app/code/Magento/AdminNotification/etc/adminhtml/menu.xml +++ b/app/code/Magento/AdminNotification/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/etc/adminhtml/routes.xml b/app/code/Magento/AdminNotification/etc/adminhtml/routes.xml index 9ca1f2d4cd1ae..a710049993270 100644 --- a/app/code/Magento/AdminNotification/etc/adminhtml/routes.xml +++ b/app/code/Magento/AdminNotification/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/etc/adminhtml/system.xml b/app/code/Magento/AdminNotification/etc/adminhtml/system.xml index 8038b914fd65b..ab0cff5f897c1 100644 --- a/app/code/Magento/AdminNotification/etc/adminhtml/system.xml +++ b/app/code/Magento/AdminNotification/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/etc/config.xml b/app/code/Magento/AdminNotification/etc/config.xml index f1a1abb44546b..c088f7b5e11a7 100644 --- a/app/code/Magento/AdminNotification/etc/config.xml +++ b/app/code/Magento/AdminNotification/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/etc/di.xml b/app/code/Magento/AdminNotification/etc/di.xml index a5f94685ed9d1..03e415dd3714e 100644 --- a/app/code/Magento/AdminNotification/etc/di.xml +++ b/app/code/Magento/AdminNotification/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/etc/module.xml b/app/code/Magento/AdminNotification/etc/module.xml index 77d9d4877ac0b..8fdfc713293d3 100644 --- a/app/code/Magento/AdminNotification/etc/module.xml +++ b/app/code/Magento/AdminNotification/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/registration.php b/app/code/Magento/AdminNotification/registration.php index ab3e6a6170db0..9bd6a540462f7 100644 --- a/app/code/Magento/AdminNotification/registration.php +++ b/app/code/Magento/AdminNotification/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_index.xml b/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_index.xml index 1d3650fa2afcb..1083e32f3c942 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_index.xml +++ b/app/code/Magento/AdminNotification/view/adminhtml/layout/adminhtml_notification_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml b/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml index a7183277e514b..836399135228a 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml +++ b/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdminNotification/view/adminhtml/requirejs-config.js b/app/code/Magento/AdminNotification/view/adminhtml/requirejs-config.js index 69739a39dd4e3..c866e796e0ade 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/AdminNotification/view/adminhtml/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -10,4 +10,4 @@ var config = { toolbarEntry: 'Magento_AdminNotification/toolbar_entry' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/AdminNotification/view/adminhtml/templates/notification/window.phtml b/app/code/Magento/AdminNotification/view/adminhtml/templates/notification/window.phtml index 260c7f9be9684..5e0e23246764a 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/templates/notification/window.phtml +++ b/app/code/Magento/AdminNotification/view/adminhtml/templates/notification/window.phtml @@ -1,6 +1,6 @@ getNoticeMessageText(); ?>
getReadDetailsText(); ?> - \ No newline at end of file + diff --git a/app/code/Magento/AdminNotification/view/adminhtml/templates/system/messages.phtml b/app/code/Magento/AdminNotification/view/adminhtml/templates/system/messages.phtml index cd4a9a88ebe0c..a70a5e97b57c3 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/templates/system/messages.phtml +++ b/app/code/Magento/AdminNotification/view/adminhtml/templates/system/messages.phtml @@ -1,6 +1,6 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/di.xml b/app/code/Magento/AdvancedPricingImportExport/etc/di.xml index c3444069c14c0..15e505282dd94 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/di.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/export.xml b/app/code/Magento/AdvancedPricingImportExport/etc/export.xml index f04e399fdfedb..da176e7bd73e1 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/export.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/export.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/import.xml b/app/code/Magento/AdvancedPricingImportExport/etc/import.xml index 711a7bf270ce6..80c8873aad387 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/import.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/import.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml index 4ae0d6516e66f..f9ad9f34b2ad6 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/AdvancedPricingImportExport/registration.php b/app/code/Magento/AdvancedPricingImportExport/registration.php index 86dcff3d60a68..a9477f3a9a1fb 100644 --- a/app/code/Magento/AdvancedPricingImportExport/registration.php +++ b/app/code/Magento/AdvancedPricingImportExport/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Authorization/etc/module.xml b/app/code/Magento/Authorization/etc/module.xml index f3fa8793f3e57..f27253870499d 100644 --- a/app/code/Magento/Authorization/etc/module.xml +++ b/app/code/Magento/Authorization/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorization/registration.php b/app/code/Magento/Authorization/registration.php index 6aabf5a16bb91..f35b17a4d6710 100644 --- a/app/code/Magento/Authorization/registration.php +++ b/app/code/Magento/Authorization/registration.php @@ -1,6 +1,6 @@ directpostFactory = $directpostFactory ?: $this->_objectManager->create(DirectpostFactory::class); + $this->logger = $logger ?: $this->_objectManager->get(LoggerInterface::class); + } + /** * Response action. * Action for Authorize.net SIM Relay Request. @@ -16,6 +56,21 @@ class BackendResponse extends \Magento\Authorizenet\Controller\Directpost\Paymen */ public function execute() { + $data = $this->getRequest()->getParams(); + /** @var Directpost $paymentMethod */ + $paymentMethod = $this->directpostFactory->create(); + if (!empty($data['store_id'])) { + $paymentMethod->setStore($data['store_id']); + } + $paymentMethod->setResponseData($data); + try { + $paymentMethod->validateResponse(); + } catch (LocalizedException $e) { + $this->logger->critical($e->getMessage()); + $this->_redirect('noroute'); + return; + } $this->_responseAction('adminhtml'); + $this->resultFactory->create(ResultFactory::TYPE_PAGE); } } diff --git a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php index 0ffe6df37b1f0..9cbfda3a37dff 100644 --- a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php +++ b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php @@ -1,6 +1,6 @@ setData('error', true); - $result->setData('error_messages', __('Unable to place order. Please try again later.')); + $result->setData( + 'error_messages', + __('An error occurred on the server. Please try to place the order again.') + ); } if ($response instanceof Http) { $response->representJson($this->jsonHelper->jsonEncode($result)); diff --git a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Redirect.php b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Redirect.php index 8745737a19bd6..84d91dc89f155 100644 --- a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Redirect.php +++ b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Redirect.php @@ -1,7 +1,7 @@ setData('error', true); - $objectFailed->setData('error_messages', __('Unable to place order. Please try again later.')); + $objectFailed->setData( + 'error_messages', + __('An error occurred on the server. Please try to place the order again.') + ); return [ [ diff --git a/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/RedirectTest.php b/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/RedirectTest.php index d11a7b8df3521..4ec5e401c9e96 100644 --- a/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/RedirectTest.php +++ b/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/RedirectTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Authorizenet/etc/adminhtml/events.xml b/app/code/Magento/Authorizenet/etc/adminhtml/events.xml index 4a669cd7d9cac..8114b8c8312cc 100644 --- a/app/code/Magento/Authorizenet/etc/adminhtml/events.xml +++ b/app/code/Magento/Authorizenet/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/etc/adminhtml/routes.xml b/app/code/Magento/Authorizenet/etc/adminhtml/routes.xml index ef3e63f2c9c90..028e1a8500d07 100644 --- a/app/code/Magento/Authorizenet/etc/adminhtml/routes.xml +++ b/app/code/Magento/Authorizenet/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/etc/adminhtml/system.xml b/app/code/Magento/Authorizenet/etc/adminhtml/system.xml index fd2fb84f0a290..3d4cde185dcd1 100644 --- a/app/code/Magento/Authorizenet/etc/adminhtml/system.xml +++ b/app/code/Magento/Authorizenet/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/etc/config.xml b/app/code/Magento/Authorizenet/etc/config.xml index 70b413b5c1a39..f5b053003f1f2 100644 --- a/app/code/Magento/Authorizenet/etc/config.xml +++ b/app/code/Magento/Authorizenet/etc/config.xml @@ -1,7 +1,7 @@ @@ -10,7 +10,7 @@ 0 - AE,VI,MC,DI + AE,VI,MC,DI,JCB,DN 0 0 diff --git a/app/code/Magento/Authorizenet/etc/di.xml b/app/code/Magento/Authorizenet/etc/di.xml index f5e595fb450e8..3bd70f25a3bf9 100644 --- a/app/code/Magento/Authorizenet/etc/di.xml +++ b/app/code/Magento/Authorizenet/etc/di.xml @@ -1,7 +1,7 @@ @@ -16,4 +16,14 @@ Magento\Authorizenet\Model\Directpost\Session\Storage + + + + 1 + 1 + 1 + 1 + + + diff --git a/app/code/Magento/Authorizenet/etc/frontend/di.xml b/app/code/Magento/Authorizenet/etc/frontend/di.xml index 7f20e067cc426..8dcf8ed700dcb 100644 --- a/app/code/Magento/Authorizenet/etc/frontend/di.xml +++ b/app/code/Magento/Authorizenet/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/etc/frontend/events.xml b/app/code/Magento/Authorizenet/etc/frontend/events.xml index bb11f4bca363a..2c6e3f12a9196 100644 --- a/app/code/Magento/Authorizenet/etc/frontend/events.xml +++ b/app/code/Magento/Authorizenet/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/etc/frontend/page_types.xml b/app/code/Magento/Authorizenet/etc/frontend/page_types.xml index 6dc50d5d28dd9..be4692b135955 100644 --- a/app/code/Magento/Authorizenet/etc/frontend/page_types.xml +++ b/app/code/Magento/Authorizenet/etc/frontend/page_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/etc/frontend/routes.xml b/app/code/Magento/Authorizenet/etc/frontend/routes.xml index 7da347a2e6381..1bdcff9f1efe1 100644 --- a/app/code/Magento/Authorizenet/etc/frontend/routes.xml +++ b/app/code/Magento/Authorizenet/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Authorizenet/etc/frontend/sections.xml b/app/code/Magento/Authorizenet/etc/frontend/sections.xml index 33c48e60e8dab..977a4b14e3e14 100644 --- a/app/code/Magento/Authorizenet/etc/frontend/sections.xml +++ b/app/code/Magento/Authorizenet/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/etc/module.xml b/app/code/Magento/Authorizenet/etc/module.xml index 75317e254efaa..91d93e56e0cad 100644 --- a/app/code/Magento/Authorizenet/etc/module.xml +++ b/app/code/Magento/Authorizenet/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/i18n/en_US.csv b/app/code/Magento/Authorizenet/i18n/en_US.csv index bb958d64bc841..7183c706dc0a2 100644 --- a/app/code/Magento/Authorizenet/i18n/en_US.csv +++ b/app/code/Magento/Authorizenet/i18n/en_US.csv @@ -2,7 +2,7 @@ "Order saving error: %1","Order saving error: %1" "Please choose a payment method.","Please choose a payment method." "We can\'t process your order right now. Please try again later.","We can\'t process your order right now. Please try again later." -"Unable to place order. Please try again later.","Unable to place order. Please try again later." +"An error occurred on the server. Please try to place the order again.","An error occurred on the server. Please try to place the order again." "Credit Card: xxxx-%1","Credit Card: xxxx-%1" "amount %1","amount %1" failed.,failed. diff --git a/app/code/Magento/Authorizenet/registration.php b/app/code/Magento/Authorizenet/registration.php index a0eab4323313e..ad98beafa744d 100644 --- a/app/code/Magento/Authorizenet/registration.php +++ b/app/code/Magento/Authorizenet/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_index.xml b/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_index.xml index aeed400c3c8fa..851cbf398750d 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_index.xml +++ b/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_index.xml @@ -1,7 +1,7 @@ @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml b/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml index 21e8f1d70fbb5..ec5ce845b8521 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml +++ b/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml @@ -1,7 +1,7 @@ @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_view.xml b/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_view.xml index d81573c891c9f..7470afcfdb7d0 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_view.xml +++ b/app/code/Magento/Authorizenet/view/adminhtml/layout/sales_order_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml index ae5a5ec6217ed..2b95af46a6b47 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml +++ b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/iframe.phtml @@ -1,6 +1,6 @@ getAdditionalInformation('fraud_details'); - \ No newline at end of file + diff --git a/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js b/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js index 69dd63cf47caa..ec0701da0da38 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js +++ b/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ (function (factory) { diff --git a/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_backendresponse.xml b/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_backendresponse.xml index 97f425e78c7de..1eedd5e26a3ed 100644 --- a/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_backendresponse.xml +++ b/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_backendresponse.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_redirect.xml b/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_redirect.xml index 97f425e78c7de..1eedd5e26a3ed 100644 --- a/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_redirect.xml +++ b/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_redirect.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_response.xml b/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_response.xml index 97f425e78c7de..1eedd5e26a3ed 100644 --- a/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_response.xml +++ b/app/code/Magento/Authorizenet/view/frontend/layout/authorizenet_directpost_payment_response.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Authorizenet/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Authorizenet/view/frontend/layout/checkout_index_index.xml index 489dddc9b15d6..1025207fec1d5 100644 --- a/app/code/Magento/Authorizenet/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Authorizenet/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ @@ -46,4 +46,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Authorizenet/view/frontend/requirejs-config.js b/app/code/Magento/Authorizenet/view/frontend/requirejs-config.js index 4af97d5775a7f..26c0e732303d0 100644 --- a/app/code/Magento/Authorizenet/view/frontend/requirejs-config.js +++ b/app/code/Magento/Authorizenet/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/authorizenet.js b/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/authorizenet.js index 83b3984735563..6f7f94eab63fc 100644 --- a/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/authorizenet.js +++ b/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/authorizenet.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ @@ -23,4 +23,4 @@ define( /** Add view logic here if needed */ return Component.extend({}); } -); \ No newline at end of file +); diff --git a/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/method-renderer/authorizenet-directpost.js b/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/method-renderer/authorizenet-directpost.js index cd05960c17633..bf6bfedbe9b6d 100644 --- a/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/method-renderer/authorizenet-directpost.js +++ b/app/code/Magento/Authorizenet/view/frontend/web/js/view/payment/method-renderer/authorizenet-directpost.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define( diff --git a/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html b/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html index 1aff94817c6eb..2de6cad54d267 100644 --- a/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html +++ b/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/App/AbstractAction.php b/app/code/Magento/Backend/App/AbstractAction.php index 89dacec902146..95045e0946831 100644 --- a/app/code/Magento/Backend/App/AbstractAction.php +++ b/app/code/Magento/Backend/App/AbstractAction.php @@ -1,6 +1,6 @@ _scopePool = $scopePool; + $this->appConfig = $appConfig ?: ObjectManager::getInstance()->get( + \Magento\Framework\App\Config::class + ); } /** - * Retrieve config value by path and scope - * - * @param string $path - * @return mixed + * @inheritdoc */ public function getValue($path) { - return $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->getValue($path); + if (isset($this->data[$path])) { + return $this->data[$path]; + } + + $configPath = ScopeConfigInterface::SCOPE_TYPE_DEFAULT; + if ($path) { + $configPath .= '/' . $path; + } + return $this->appConfig->get(System::CONFIG_TYPE, $configPath); } /** - * Set config value in the corresponding config scope - * - * @param string $path - * @param mixed $value - * @return void + * @inheritdoc */ public function setValue($path, $value) { - $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->setValue($path, $value); + $this->data[$path] = $value; } /** - * Retrieve config flag - * - * @param string $path - * @return bool + * @inheritdoc */ public function isSetFlag($path) { - return !!$this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->getValue($path); + $configPath = ScopeConfigInterface::SCOPE_TYPE_DEFAULT; + if ($path) { + $configPath .= '/' . $path; + } + return (bool) $this->appConfig->get(System::CONFIG_TYPE, $configPath); } } diff --git a/app/code/Magento/Backend/App/ConfigInterface.php b/app/code/Magento/Backend/App/ConfigInterface.php index 4000b54cc9834..1e183bc8fd1bd 100644 --- a/app/code/Magento/Backend/App/ConfigInterface.php +++ b/app/code/Magento/Backend/App/ConfigInterface.php @@ -2,7 +2,7 @@ /** * Default application path for backend area * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Backend\App; @@ -15,6 +15,8 @@ interface ConfigInterface /** * Retrieve config value by path * + * Path should looks like keys imploded by "/". For example scopes/stores/admin + * * @param string $path * @return mixed * @api @@ -24,6 +26,7 @@ public function getValue($path); /** * Set config value * + * @deprecated * @param string $path * @param mixed $value * @return void @@ -34,6 +37,8 @@ public function setValue($path, $value); /** * Retrieve config flag * + * Path should looks like keys imploded by "/". For example scopes/stores/admin + * * @param string $path * @return bool * @api diff --git a/app/code/Magento/Backend/App/DefaultPath.php b/app/code/Magento/Backend/App/DefaultPath.php index ef3d502db8ab8..9a25e328bde52 100644 --- a/app/code/Magento/Backend/App/DefaultPath.php +++ b/app/code/Magento/Backend/App/DefaultPath.php @@ -2,7 +2,7 @@ /** * Default application path for backend area * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Backend\App; diff --git a/app/code/Magento/Backend/App/Request/PathInfoProcessor.php b/app/code/Magento/Backend/App/Request/PathInfoProcessor.php index 08e115e9ec795..e0890ce917897 100644 --- a/app/code/Magento/Backend/App/Request/PathInfoProcessor.php +++ b/app/code/Magento/Backend/App/Request/PathInfoProcessor.php @@ -2,7 +2,7 @@ /** * Prevents path info processing for admin store * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Backend\App\Request; diff --git a/app/code/Magento/Backend/App/Response/Http/FileFactory.php b/app/code/Magento/Backend/App/Response/Http/FileFactory.php index dec52cdb646b0..1c67275a7fc67 100644 --- a/app/code/Magento/Backend/App/Response/Http/FileFactory.php +++ b/app/code/Magento/Backend/App/Response/Http/FileFactory.php @@ -1,6 +1,6 @@ _storeManager->getWebsites(); if ($websiteIds = $this->getWebsiteIds()) { - foreach (array_keys($websites) as $websiteId) { - if (!in_array($websiteId, $websiteIds)) { - unset($websites[$websiteId]); - } - } + $websites = array_intersect_key($websites, array_flip($websiteIds)); } return $websites; } diff --git a/app/code/Magento/Backend/Block/Store/Switcher/Form/Renderer/Fieldset.php b/app/code/Magento/Backend/Block/Store/Switcher/Form/Renderer/Fieldset.php index 8e0d823281b8e..e117b848926de 100644 --- a/app/code/Magento/Backend/Block/Store/Switcher/Form/Renderer/Fieldset.php +++ b/app/code/Magento/Backend/Block/Store/Switcher/Form/Renderer/Fieldset.php @@ -1,6 +1,6 @@ */ class Currency extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer { @@ -49,6 +45,11 @@ class Currency extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Abstra */ protected $_localeCurrency; + /** + * @var \Magento\Framework\Pricing\PriceCurrencyInterface + */ + private $priceCurrency; + /** * @param \Magento\Backend\Block\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -76,6 +77,23 @@ public function __construct( $this->_defaultBaseCurrency = $currencyFactory->create()->load($defaultBaseCurrencyCode); } + /** + * Get price currency + * + * @return \Magento\Framework\Pricing\PriceCurrencyInterface + * + * @deprecated + */ + private function getPriceCurrency() + { + if ($this->priceCurrency === null) { + $this->priceCurrency = \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\Pricing\PriceCurrencyInterface::class + ); + } + return $this->priceCurrency; + } + /** * Renders grid column * @@ -84,15 +102,9 @@ public function __construct( */ public function render(\Magento\Framework\DataObject $row) { - if ($data = (string)$this->_getValue($row)) { - $currency_code = $this->_getCurrencyCode($row); - $data = floatval($data) * $this->_getRate($row); - $sign = (bool)(int)$this->getColumn()->getShowNumberSign() && $data > 0 ? '+' : ''; - $data = sprintf("%f", $data); - $data = $this->_localeCurrency->getCurrency($currency_code)->toCurrency($data); - return $sign . $data; - } - return $this->getColumn()->getDefault(); + $price = $this->_getValue($row) ? $this->_getValue($row) : $this->getColumn()->getDefault(); + $displayPrice = $this->getPriceCurrency()->convertAndFormat($price, false); + return $displayPrice; } /** diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php index 52761266b644d..55f91b1c7fc67 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php @@ -1,6 +1,6 @@ sectionPool = $this->getMock( - 'Magento\Framework\App\Config\ScopePool', - ['getScope', 'clean'], + $this->appConfig = $this->getMock( + 'Magento\Framework\App\Config', + ['get'], [], '', false ); - $this->model = new \Magento\Backend\App\Config($this->sectionPool); + $this->model = new \Magento\Backend\App\Config( + $this->getMock(\Magento\Framework\App\Config\ScopePool::class, [], [], '', false, false), + $this->appConfig + ); } public function testGetValue() { $expectedValue = 'some value'; $path = 'some path'; - $configData = $this->getConfigDataMock('getValue'); - $configData->expects( - $this->once() - )->method( - 'getValue' - )->with( - $this->equalTo($path) - )->will( - $this->returnValue($expectedValue) - ); - $this->sectionPool->expects( + $this->appConfig->expects( $this->once() )->method( - 'getScope' + 'get' )->with( - $this->equalTo('default'), + $this->equalTo('system'), + $this->equalTo('default/' . $path), $this->isNull() )->will( - $this->returnValue($configData) + $this->returnValue($expectedValue) ); $this->assertEquals($expectedValue, $this->model->getValue($path)); } - public function testSetValue() - { - $value = 'some value'; - $path = 'some path'; - $configData = $this->getConfigDataMock('setValue'); - $configData->expects($this->once())->method('setValue')->with($this->equalTo($path), $this->equalTo($value)); - $this->sectionPool->expects( - $this->once() - )->method( - 'getScope' - )->with( - $this->equalTo('default'), - $this->isNull() - )->will( - $this->returnValue($configData) - ); - $this->model->setValue($path, $value); - } - /** + * @param string $configPath * @param mixed $configValue * @param bool $expectedResult * @dataProvider isSetFlagDataProvider */ - public function testIsSetFlag($configValue, $expectedResult) + public function testIsSetFlag($configPath, $configValue, $expectedResult) { - $path = 'some path'; - $configData = $this->getConfigDataMock('getValue'); - $configData->expects( - $this->once() + $this->appConfig->expects( + $this->any() )->method( - 'getValue' + 'get' )->with( - $this->equalTo($path) + $this->equalTo('system'), + $this->equalTo('default/' . $configPath) )->will( $this->returnValue($configValue) ); - $this->sectionPool->expects( - $this->once() - )->method( - 'getScope' - )->with( - $this->equalTo('default'), - $this->isNull() - )->will( - $this->returnValue($configData) - ); - $this->assertEquals($expectedResult, $this->model->isSetFlag($path)); + $this->assertEquals($expectedResult, $this->model->isSetFlag($configPath)); } public function isSetFlagDataProvider() { return [ - [0, false], - [true, true], - ['0', false], - ['', false], - ['some string', true], - [1, true] + ['a', 0, false], + ['b', true, true], + ['c', '0', false], + ['d', '', false], + ['e', 'some string', true], + ['f', 1, true] ]; } diff --git a/app/code/Magento/Backend/Test/Unit/App/Response/Http/FileFactoryTest.php b/app/code/Magento/Backend/Test/Unit/App/Response/Http/FileFactoryTest.php index 7342c5ad40e97..78e05d224068b 100644 --- a/app/code/Magento/Backend/Test/Unit/App/Response/Http/FileFactoryTest.php +++ b/app/code/Magento/Backend/Test/Unit/App/Response/Http/FileFactoryTest.php @@ -1,6 +1,6 @@ storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); + $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $context = $objectHelper->getObject( + \Magento\Backend\Block\Template\Context::class, + [ + 'storeManager' => $this->storeManagerMock, + ] + ); + + $this->switcherBlock = $objectHelper->getObject( + \Magento\Backend\Block\Store\Switcher::class, + ['context' => $context] + ); + } + + public function testGetWebsites() + { + $websiteMock = $this->getMock(\Magento\Store\Model\Website::class, [], [], '', false); + $websites = [0 => $websiteMock, 1 => $websiteMock]; + $this->storeManagerMock->expects($this->once())->method('getWebsites')->will($this->returnValue($websites)); + $this->assertEquals($websites, $this->switcherBlock->getWebsites()); + } + + public function testGetWebsitesIfSetWebsiteIds() + { + $websiteMock = $this->getMock(\Magento\Store\Model\Website::class, [], [], '', false); + $websites = [0 => $websiteMock, 1 => $websiteMock]; + $this->storeManagerMock->expects($this->once())->method('getWebsites')->will($this->returnValue($websites)); + + $this->switcherBlock->setWebsiteIds([1]); + $expected = [1 => $websiteMock]; + $this->assertEquals($expected, $this->switcherBlock->getWebsites()); + } +} diff --git a/app/code/Magento/Backend/Test/Unit/Block/Widget/Button/SplitTest.php b/app/code/Magento/Backend/Test/Unit/Block/Widget/Button/SplitTest.php index 71c54fd889258..aa98f4aa62989 100644 --- a/app/code/Magento/Backend/Test/Unit/Block/Widget/Button/SplitTest.php +++ b/app/code/Magento/Backend/Test/Unit/Block/Widget/Button/SplitTest.php @@ -1,6 +1,6 @@ _storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); - $this->_localeMock = $this->getMock('Magento\Framework\Locale\CurrencyInterface'); - $this->_requestMock = $this->getMock('Magento\Framework\App\RequestInterface'); + $this->_storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); + $this->_localeMock = $this->getMock(\Magento\Framework\Locale\CurrencyInterface::class); + $this->_requestMock = $this->getMock(\Magento\Framework\App\RequestInterface::class); $this->_curLocatorMock = $this->getMock( - 'Magento\Directory\Model\Currency\DefaultLocator', + \Magento\Directory\Model\Currency\DefaultLocator::class, [], [], '', false ); $this->_columnMock = $this->getMock( - 'Magento\Backend\Block\Widget\Grid\Column', + \Magento\Backend\Block\Widget\Grid\Column::class, ['getIndex'], [], '', @@ -69,10 +74,10 @@ protected function setUp() ); $this->_columnMock->expects($this->any())->method('getIndex')->will($this->returnValue('columnIndex')); - $this->_currencyMock = $this->getMock('Magento\Directory\Model\Currency', [], [], '', false); + $this->_currencyMock = $this->getMock(\Magento\Directory\Model\Currency::class, [], [], '', false); $this->_currencyMock->expects($this->any())->method('load')->will($this->returnSelf()); $currencyFactoryMock = $this->getMock( - 'Magento\Directory\Model\CurrencyFactory', + \Magento\Directory\Model\CurrencyFactory::class, ['create'], [], '', @@ -80,11 +85,11 @@ protected function setUp() ); $currencyFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_currencyMock)); - $this->_row = new \Magento\Framework\DataObject(['columnIndex' => '10']); + $this->_row = new \Magento\Framework\DataObject(['columnIndex' => '$10.00']); $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_blockCurrency = $helper->getObject( - 'Magento\Backend\Block\Widget\Grid\Column\Renderer\Currency', + \Magento\Backend\Block\Widget\Grid\Column\Renderer\Currency::class, [ 'storeManager' => $this->_storeManagerMock, 'localeCurrency' => $this->_localeMock, @@ -95,6 +100,21 @@ protected function setUp() ); $this->_blockCurrency->setColumn($this->_columnMock); + + $this->priceCurrencyMock = $this->getMockForAbstractClass( + \Magento\Framework\Pricing\PriceCurrencyInterface::class, + [], + '', + false, + true, + true, + ['convertAndFormat'] + ); + $helper->setBackwardCompatibleProperty( + $this->_blockCurrency, + 'priceCurrency', + $this->priceCurrencyMock + ); } protected function tearDown() @@ -113,46 +133,11 @@ protected function tearDown() */ public function testRenderWithDefaultCurrency() { - $this->_currencyMock->expects( - $this->once() - )->method( - 'getRate' - )->with( - 'defaultCurrency' - )->will( - $this->returnValue(1.5) - ); - - $this->_curLocatorMock->expects( - $this->any() - )->method( - 'getDefaultCurrency' - )->with( - $this->_requestMock - )->will( - $this->returnValue('defaultCurrency') - ); - - $currLocaleMock = $this->getMock('Zend_Currency', [], [], '', false); - $currLocaleMock->expects( - $this->once() - )->method( - 'toCurrency' - )->with( - 15.0000 - )->will( - $this->returnValue('15USD') - ); - $this->_localeMock->expects( - $this->once() - )->method( - 'getCurrency' - )->with( - 'defaultCurrency' - )->will( - $this->returnValue($currLocaleMock) - ); + $this->priceCurrencyMock->expects($this->once()) + ->method('convertAndFormat') + ->with('$10.00', false) + ->willReturn('$10.00'); - $this->assertEquals('15USD', $this->_blockCurrency->render($this->_row)); + $this->assertEquals('$10.00', $this->_blockCurrency->render($this->_row)); } } diff --git a/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/Column/Renderer/Radio/ExtendedTest.php b/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/Column/Renderer/Radio/ExtendedTest.php index 2432eae04c521..ba871e1130eca 100644 --- a/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/Column/Renderer/Radio/ExtendedTest.php +++ b/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/Column/Renderer/Radio/ExtendedTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/Test/Unit/Model/Menu/Config/_files/valid_menu.xml b/app/code/Magento/Backend/Test/Unit/Model/Menu/Config/_files/valid_menu.xml index 4627fb49a031f..d60f5a0cd37da 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/Menu/Config/_files/valid_menu.xml +++ b/app/code/Magento/Backend/Test/Unit/Model/Menu/Config/_files/valid_menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/Test/Unit/Model/Menu/ConfigTest.php b/app/code/Magento/Backend/Test/Unit/Model/Menu/ConfigTest.php index 4a760c9a7f32f..7b25a07e51aba 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/Menu/ConfigTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/Menu/ConfigTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/Test/Unit/Model/_files/menu_merged.xml b/app/code/Magento/Backend/Test/Unit/Model/_files/menu_merged.xml index 55ed5a90d8025..e7ac5aec547d2 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/_files/menu_merged.xml +++ b/app/code/Magento/Backend/Test/Unit/Model/_files/menu_merged.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/Test/Unit/Setup/ConfigOptionsListTest.php b/app/code/Magento/Backend/Test/Unit/Setup/ConfigOptionsListTest.php index a265b3c43fcb0..89a87de6f12f5 100644 --- a/app/code/Magento/Backend/Test/Unit/Setup/ConfigOptionsListTest.php +++ b/app/code/Magento/Backend/Test/Unit/Setup/ConfigOptionsListTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/etc/adminhtml/di.xml b/app/code/Magento/Backend/etc/adminhtml/di.xml index fcf2cc02e9fb9..c38c284f3c560 100644 --- a/app/code/Magento/Backend/etc/adminhtml/di.xml +++ b/app/code/Magento/Backend/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/etc/adminhtml/menu.xml b/app/code/Magento/Backend/etc/adminhtml/menu.xml index 1a754291cb47c..d7d57b7953c77 100644 --- a/app/code/Magento/Backend/etc/adminhtml/menu.xml +++ b/app/code/Magento/Backend/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/etc/adminhtml/routes.xml b/app/code/Magento/Backend/etc/adminhtml/routes.xml index 232ac5222daea..2f3857c91c5c0 100644 --- a/app/code/Magento/Backend/etc/adminhtml/routes.xml +++ b/app/code/Magento/Backend/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 7297f3a6c2299..813a097ea6bf3 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ @@ -198,7 +198,7 @@ Magento_Config::config_general - + Magento\Directory\Model\Config\Source\Country 1 diff --git a/app/code/Magento/Backend/etc/config.xml b/app/code/Magento/Backend/etc/config.xml index 459dd377e36ba..ee10f5f4c1683 100644 --- a/app/code/Magento/Backend/etc/config.xml +++ b/app/code/Magento/Backend/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/etc/crontab.xml b/app/code/Magento/Backend/etc/crontab.xml index 0c7e18e977549..4f6450a7226ae 100644 --- a/app/code/Magento/Backend/etc/crontab.xml +++ b/app/code/Magento/Backend/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/etc/di.xml b/app/code/Magento/Backend/etc/di.xml index 7307bbe09f1b4..2ed8a77bbac43 100644 --- a/app/code/Magento/Backend/etc/di.xml +++ b/app/code/Magento/Backend/etc/di.xml @@ -1,7 +1,7 @@ @@ -214,4 +214,22 @@ + + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + diff --git a/app/code/Magento/Backend/etc/menu.xsd b/app/code/Magento/Backend/etc/menu.xsd index 05df67a5e2bbd..5c5ad89bd89c1 100644 --- a/app/code/Magento/Backend/etc/menu.xsd +++ b/app/code/Magento/Backend/etc/menu.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/etc/module.xml b/app/code/Magento/Backend/etc/module.xml index db6b19407c73b..b7f188e78d34e 100644 --- a/app/code/Magento/Backend/etc/module.xml +++ b/app/code/Magento/Backend/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/etc/webapi.xml b/app/code/Magento/Backend/etc/webapi.xml index d01bbafa8e676..14d4dccc78cbe 100644 --- a/app/code/Magento/Backend/etc/webapi.xml +++ b/app/code/Magento/Backend/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 252269ba97ffb..08a28eb95579b 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -232,7 +232,7 @@ password,password "Reload Data","Reload Data" "Browse Files...","Browse Files..." Magento,Magento -"Copyright© %1 Magento Commerce Inc. All rights reserved.","Copyright© %1 Magento Commerce Inc. All rights reserved." +"Copyright © %1 Magento, Inc. All rights reserved.","Copyright © %1 Magento, Inc. All rights reserved." "ver. %1","ver. %1" "Magento Admin Panel","Magento Admin Panel" "Account Setting","Account Setting" diff --git a/app/code/Magento/Backend/registration.php b/app/code/Magento/Backend/registration.php index 5e9d9fe4dabe7..fac71f545151f 100644 --- a/app/code/Magento/Backend/registration.php +++ b/app/code/Magento/Backend/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_auth_login.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_auth_login.xml index d8462aeedfa1a..bb7370b3317a4 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_auth_login.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_auth_login.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml index 3e61fec077c6e..6374f0d31b6bb 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_index.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_index.xml index 8edb476a2b555..77ba8f6f39824 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_index.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersmost.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersmost.xml index 39b3db77d505e..31b3ff2c44bc1 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersmost.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersmost.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersnewest.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersnewest.xml index ce83aa64faafb..ce4e20140eb54 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersnewest.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_customersnewest.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml index 8b36caac55b82..b353b81aa1b7c 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_productsviewed.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_productsviewed.xml index d55194f4dbb43..4621d83dc6753 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_productsviewed.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_productsviewed.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_denied.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_denied.xml index e8754242dfd2f..fac9407cc3298 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_denied.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_denied.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_noroute.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_noroute.xml index 4872a39a16e45..598bdf490e8a5 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_noroute.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_noroute.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_account_index.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_account_index.xml index 581f6d2ee5972..dfc27d5e6b5e0 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_account_index.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_account_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_edit.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_edit.xml index 4f5d3a778a120..91469c51e06c9 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_edit.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid.xml index 4a0c8a711f5ea..bda7f3883adce 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml index 3d2c4dff37228..a39aee9813286 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_grid_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_index.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_index.xml index 8ae928a3cadcf..7412c983cff8b 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_index.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_design_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml index 320ce474bc392..0521a87831663 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_grid_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_index.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_index.xml index 64d7968bd1772..2abd830f5fa37 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_index.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_system_store_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/default.xml b/app/code/Magento/Backend/view/adminhtml/layout/default.xml index c957f3b49c6b8..1ab7ef1e6cf60 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/default.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/editor.xml b/app/code/Magento/Backend/view/adminhtml/layout/editor.xml index 9109e54ac357b..2c34667c0502e 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/editor.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/editor.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/empty.xml b/app/code/Magento/Backend/view/adminhtml/layout/empty.xml index 7509438df2553..e01b48cc71b11 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/empty.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/empty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/formkey.xml b/app/code/Magento/Backend/view/adminhtml/layout/formkey.xml index 50b1784b33210..6ba9743703ed4 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/formkey.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/formkey.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/overlay_popup.xml b/app/code/Magento/Backend/view/adminhtml/layout/overlay_popup.xml index 67304406b201b..8a48fcca66c0e 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/overlay_popup.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/overlay_popup.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/layout/popup.xml b/app/code/Magento/Backend/view/adminhtml/layout/popup.xml index 825094937cd9d..dd65940af81e5 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/popup.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/popup.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/requirejs-config.js b/app/code/Magento/Backend/view/adminhtml/requirejs-config.js index 9c1350ea268cb..2703ea79738b7 100644 --- a/app/code/Magento/Backend/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/Backend/view/adminhtml/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*eslint no-unused-vars: 0*/ diff --git a/app/code/Magento/Backend/view/adminhtml/templates/admin/access_denied.phtml b/app/code/Magento/Backend/view/adminhtml/templates/admin/access_denied.phtml index 7ff08dcc32422..32910c9978d2d 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/admin/access_denied.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/admin/access_denied.phtml @@ -1,6 +1,6 @@ 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 0968047053bc5..1716af3ec14c4 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/admin/login.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/admin/login.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/templates/admin/overlay_popup.phtml b/app/code/Magento/Backend/view/adminhtml/templates/admin/overlay_popup.phtml index ab29376b3b573..e95b063599daa 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/admin/overlay_popup.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/admin/overlay_popup.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/templates/media/uploader.phtml b/app/code/Magento/Backend/view/adminhtml/templates/media/uploader.phtml index e93b143e039c8..aeac3fd33248c 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/media/uploader.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/media/uploader.phtml @@ -1,6 +1,6 @@ - + diff --git a/app/code/Magento/Backend/view/adminhtml/templates/page/footer.phtml b/app/code/Magento/Backend/view/adminhtml/templates/page/footer.phtml index 54f5220be16cc..102b80c7373c2 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/page/footer.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/page/footer.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/templates/page/notices.phtml b/app/code/Magento/Backend/view/adminhtml/templates/page/notices.phtml index 987afc07df489..b4e7c2d7f50a8 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/page/notices.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/page/notices.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/templates/system/design/index.phtml b/app/code/Magento/Backend/view/adminhtml/templates/system/design/index.phtml index 3b5748da54823..2cdb9f451a86f 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/system/design/index.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/system/design/index.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/accordion.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/accordion.phtml index 52e4d895c1dc1..060ee67e9a7b2 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/accordion.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/accordion.phtml @@ -1,6 +1,6 @@ getExportButtonHtml() ?> - \ No newline at end of file + diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml index 62ff8d2752362..838e22f16493a 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/ui_component/design_config_listing.xml b/app/code/Magento/Backend/view/adminhtml/ui_component/design_config_listing.xml index c72e5f3c9079e..c299f217c8df7 100644 --- a/app/code/Magento/Backend/view/adminhtml/ui_component/design_config_listing.xml +++ b/app/code/Magento/Backend/view/adminhtml/ui_component/design_config_listing.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/web/js/bootstrap/editor.js b/app/code/Magento/Backend/view/adminhtml/web/js/bootstrap/editor.js index 08ff14f84f660..de003bb3b8d08 100644 --- a/app/code/Magento/Backend/view/adminhtml/web/js/bootstrap/editor.js +++ b/app/code/Magento/Backend/view/adminhtml/web/js/bootstrap/editor.js @@ -1,9 +1,9 @@ /** * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ require([ "Magento_Variable/variables", "mage/adminhtml/browser" -]); \ No newline at end of file +]); diff --git a/app/code/Magento/Backend/view/adminhtml/web/js/media-uploader.js b/app/code/Magento/Backend/view/adminhtml/web/js/media-uploader.js index 18f44da26109a..fe7c8dd7cb800 100644 --- a/app/code/Magento/Backend/view/adminhtml/web/js/media-uploader.js +++ b/app/code/Magento/Backend/view/adminhtml/web/js/media-uploader.js @@ -1,6 +1,6 @@ /** * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global byteConvert*/ diff --git a/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/cells/action-delete.html b/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/cells/action-delete.html index 117eee7e69fdc..d58d3e8990e64 100644 --- a/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/cells/action-delete.html +++ b/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/cells/action-delete.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/grid.html b/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/grid.html index 6e24ee96a62a0..3de4b65aa2a5f 100644 --- a/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/grid.html +++ b/app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/grid.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backend/view/adminhtml/web/template/form/element/helper/fallback-reset-link.html b/app/code/Magento/Backend/view/adminhtml/web/template/form/element/helper/fallback-reset-link.html index 25b584f89f9fa..f788dbb6fbe20 100644 --- a/app/code/Magento/Backend/view/adminhtml/web/template/form/element/helper/fallback-reset-link.html +++ b/app/code/Magento/Backend/view/adminhtml/web/template/form/element/helper/fallback-reset-link.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backup/Block/Adminhtml/Backup.php b/app/code/Magento/Backup/Block/Adminhtml/Backup.php index 472b97123f2dc..4d4624caa3b24 100644 --- a/app/code/Magento/Backup/Block/Adminhtml/Backup.php +++ b/app/code/Magento/Backup/Block/Adminhtml/Backup.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backup/etc/adminhtml/menu.xml b/app/code/Magento/Backup/etc/adminhtml/menu.xml index 812b1cb9d0df8..32c2936697fac 100644 --- a/app/code/Magento/Backup/etc/adminhtml/menu.xml +++ b/app/code/Magento/Backup/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/etc/adminhtml/routes.xml b/app/code/Magento/Backup/etc/adminhtml/routes.xml index 3e0e606439eed..232c0ca0f9d6a 100644 --- a/app/code/Magento/Backup/etc/adminhtml/routes.xml +++ b/app/code/Magento/Backup/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/etc/adminhtml/system.xml b/app/code/Magento/Backup/etc/adminhtml/system.xml index 69e15030ad6a7..325395826df15 100644 --- a/app/code/Magento/Backup/etc/adminhtml/system.xml +++ b/app/code/Magento/Backup/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/etc/crontab.xml b/app/code/Magento/Backup/etc/crontab.xml index a0a1fdbdf2a15..150751eb94a1f 100644 --- a/app/code/Magento/Backup/etc/crontab.xml +++ b/app/code/Magento/Backup/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/etc/di.xml b/app/code/Magento/Backup/etc/di.xml index f9371f4a249bf..fc9c5bb2ff025 100644 --- a/app/code/Magento/Backup/etc/di.xml +++ b/app/code/Magento/Backup/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/etc/module.xml b/app/code/Magento/Backup/etc/module.xml index 9edced27b2247..9f4fe8da7ac1d 100644 --- a/app/code/Magento/Backup/etc/module.xml +++ b/app/code/Magento/Backup/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/registration.php b/app/code/Magento/Backup/registration.php index c158dddf70a65..d429ad8208552 100644 --- a/app/code/Magento/Backup/registration.php +++ b/app/code/Magento/Backup/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_grid.xml b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_grid.xml index 1f6e1cbec7f10..03b4aa4a7f4ad 100644 --- a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_grid.xml +++ b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_index.xml b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_index.xml index 42c3d766b6997..242534d006e37 100644 --- a/app/code/Magento/Backup/view/adminhtml/layout/backup_index_index.xml +++ b/app/code/Magento/Backup/view/adminhtml/layout/backup_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Backup/view/adminhtml/templates/backup/dialogs.phtml b/app/code/Magento/Backup/view/adminhtml/templates/backup/dialogs.phtml index 19cd8877d8793..502206238416c 100644 --- a/app/code/Magento/Backup/view/adminhtml/templates/backup/dialogs.phtml +++ b/app/code/Magento/Backup/view/adminhtml/templates/backup/dialogs.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml b/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml index 0fff82609ed11..ace0931b60428 100644 --- a/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml +++ b/app/code/Magento/Backup/view/adminhtml/templates/backup/list.phtml @@ -1,6 +1,6 @@ config = $config; + } + + /** + * @inheritdoc + */ + public function getIconUrl() + { + return $this->config->getPayPalIcon()['url']; + } + + /** + * @inheritdoc + */ + public function getIconHeight() + { + return $this->config->getPayPalIcon()['height']; + } + + /** + * @inheritdoc + */ + public function getIconWidth() + { + return $this->config->getPayPalIcon()['width']; + } + + /** + * Can render specified token + * + * @param PaymentTokenInterface $token + * @return boolean + */ + public function canRender(PaymentTokenInterface $token) + { + return $token->getPaymentMethodCode() === ConfigProvider::PAYPAL_CODE; + } + + /** + * Get email of PayPal payer + * @return string + */ + public function getPayerEmail() + { + return $this->getTokenDetails()['payerEmail']; + } +} diff --git a/app/code/Magento/Braintree/Block/Form.php b/app/code/Magento/Braintree/Block/Form.php index cefc0a8418243..9b9e96baa71e8 100644 --- a/app/code/Magento/Braintree/Block/Form.php +++ b/app/code/Magento/Braintree/Block/Form.php @@ -1,6 +1,6 @@ filterBuilder->setField('payment_id') - ->setValue($payment->getId()) - ->create(); + $this->searchCriteriaBuilder->addFilters( + [ + $this->filterBuilder + ->setField('payment_id') + ->setValue($payment->getId()) + ->create(), + ] + ); - $filters[] = $this->filterBuilder->setField('txn_type') - ->setValue(TransactionInterface::TYPE_CAPTURE) - ->create(); + $this->searchCriteriaBuilder->addFilters( + [ + $this->filterBuilder + ->setField('txn_type') + ->setValue(TransactionInterface::TYPE_CAPTURE) + ->create(), + ] + ); - $searchCriteria = $this->searchCriteriaBuilder->addFilters($filters) - ->create(); + $searchCriteria = $this->searchCriteriaBuilder->create(); $count = $this->transactionRepository->getList($searchCriteria)->getTotalCount(); return (boolean) $count; diff --git a/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php b/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php index a7cdae83a96e9..3e77378af3a79 100644 --- a/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php +++ b/app/code/Magento/Braintree/Gateway/Command/GetPaymentNonceCommand.php @@ -1,6 +1,6 @@ getValue(self::KEY_ACTIVE); } + + /** + * Get list of configured dynamic descriptors + * @return array + */ + public function getDynamicDescriptors() + { + $values = []; + foreach (self::$dynamicDescriptorKeys as $key) { + $value = $this->getValue('descriptor_' . $key); + if (!empty($value)) { + $values[$key] = $value; + } + } + return $values; + } + + /** + * Get Merchant account ID + * + * @return string + */ + public function getMerchantAccountId() + { + return $this->getValue(self::KEY_MERCHANT_ACCOUNT_ID); + } } diff --git a/app/code/Magento/Braintree/Gateway/Config/PayPal/Config.php b/app/code/Magento/Braintree/Gateway/Config/PayPal/Config.php index 06ff216acd49c..3f34afd0717db 100644 --- a/app/code/Magento/Braintree/Gateway/Config/PayPal/Config.php +++ b/app/code/Magento/Braintree/Gateway/Config/PayPal/Config.php @@ -1,10 +1,13 @@ ccConfig = $ccConfig; + } + /** * Get Payment configuration status * @@ -79,4 +102,32 @@ public function getTitle() { return $this->getValue(self::KEY_TITLE); } + + /** + * Is need to skip order review + * @return bool + */ + public function isSkipOrderReview() + { + return (bool) $this->getValue('skip_order_review'); + } + + /** + * Get PayPal icon + * @return array + */ + public function getPayPalIcon() + { + if (empty($this->icon)) { + $asset = $this->ccConfig->createAsset('Magento_Braintree::images/paypal.png'); + list($width, $height) = getimagesize($asset->getSourceFile()); + $this->icon = [ + 'url' => $asset->getUrl(), + 'width' => $width, + 'height' => $height + ]; + } + + return $this->icon; + } } diff --git a/app/code/Magento/Braintree/Gateway/Helper/SubjectReader.php b/app/code/Magento/Braintree/Gateway/Helper/SubjectReader.php index c91abc49b2dd2..b2cc3637f6b06 100644 --- a/app/code/Magento/Braintree/Gateway/Helper/SubjectReader.php +++ b/app/code/Magento/Braintree/Gateway/Helper/SubjectReader.php @@ -1,6 +1,6 @@ config = $config; + } + + /** + * @inheritdoc + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function build(array $buildSubject) + { + $values = $this->config->getDynamicDescriptors(); + return !empty($values) ? [self::$descriptorKey => $values] : []; + } +} diff --git a/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php index 6dcbcbd266a9d..a50e54aa24ade 100644 --- a/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php +++ b/app/code/Magento/Braintree/Gateway/Request/KountPaymentDataBuilder.php @@ -1,6 +1,6 @@ subjectReader = $subjectReader; + } + + /** + * @inheritdoc + */ + public function build(array $buildSubject) + { + $result = []; + $paymentDO = $this->subjectReader->readPayment($buildSubject); + + $payment = $paymentDO->getPayment(); + $data = $payment->getAdditionalInformation(); + if (!empty($data[DataAssignObserver::DEVICE_DATA])) { + $result[self::$deviceDataKey] = $data[DataAssignObserver::DEVICE_DATA]; + } + + return $result; + } +} diff --git a/app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php new file mode 100644 index 0000000000000..9adbf6a7f3217 --- /dev/null +++ b/app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php @@ -0,0 +1,60 @@ +subjectReader = $subjectReader; + } + + /** + * @inheritdoc + */ + public function build(array $buildSubject) + { + $result = []; + $paymentDO = $this->subjectReader->readPayment($buildSubject); + + $payment = $paymentDO->getPayment(); + $data = $payment->getAdditionalInformation(); + if (!empty($data[VaultConfigProvider::IS_ACTIVE_CODE])) { + $result[self::$optionsKey] = [ + self::$storeInVaultOnSuccess => true + ]; + } + + return $result; + } +} diff --git a/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php index 9591d24465487..ac2eff5097f5f 100644 --- a/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php +++ b/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php @@ -1,6 +1,6 @@ $order->getOrderIncrementId() ]; - $merchantAccountId = $this->config->getValue(Config::KEY_MERCHANT_ACCOUNT_ID); + $merchantAccountId = $this->config->getMerchantAccountId(); if (!empty($merchantAccountId)) { $result[self::MERCHANT_ACCOUNT_ID] = $merchantAccountId; } diff --git a/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php index 82679d9e92186..5bf4e9b534d90 100644 --- a/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php +++ b/app/code/Magento/Braintree/Gateway/Request/RefundDataBuilder.php @@ -1,6 +1,6 @@ paymentTokenFactory = $paymentTokenFactory; + $this->paymentExtensionFactory = $paymentExtensionFactory; + $this->subjectReader = $subjectReader; + $this->dateTimeFactory = $dateTimeFactory; + } + + /** + * @inheritdoc + */ + public function handle(array $handlingSubject, array $response) + { + $paymentDO = $this->subjectReader->readPayment($handlingSubject); + $transaction = $this->subjectReader->readTransaction($response); + $payment = $paymentDO->getPayment(); + + // add vault payment token entity to extension attributes + $paymentToken = $this->getVaultPaymentToken($transaction); + if ($paymentToken !== null) { + $extensionAttributes = $this->getExtensionAttributes($payment); + $extensionAttributes->setVaultPaymentToken($paymentToken); + } + } + + /** + * Get vault payment token entity + * + * @param \Braintree\Transaction $transaction + * @return PaymentTokenInterface|null + */ + private function getVaultPaymentToken(Transaction $transaction) + { + // Check token existing in gateway response + $token = $transaction->paypalDetails->token; + if (empty($token)) { + return null; + } + + /** @var PaymentTokenInterface $paymentToken */ + $paymentToken = $this->paymentTokenFactory->create(); + $paymentToken->setGatewayToken($token); + $paymentToken->setExpiresAt($this->getExpirationDate()); + $details = json_encode([ + 'payerEmail' => $transaction->paypalDetails->payerEmail + ]); + $paymentToken->setTokenDetails($details); + + return $paymentToken; + } + + /** + * @return string + */ + private function getExpirationDate() + { + $expDate = $this->dateTimeFactory->create('now', new \DateTimeZone('UTC')); + $expDate->add(new \DateInterval('P1Y')); + return $expDate->format('Y-m-d 00:00:00'); + } + + /** + * Get payment extension attributes + * @param InfoInterface $payment + * @return OrderPaymentExtensionInterface + */ + private function getExtensionAttributes(InfoInterface $payment) + { + $extensionAttributes = $payment->getExtensionAttributes(); + if ($extensionAttributes === null) { + $extensionAttributes = $this->paymentExtensionFactory->create(); + $payment->setExtensionAttributes($extensionAttributes); + } + return $extensionAttributes; + } +} diff --git a/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php index b58cc2839ad2b..77bf9305ca0bc 100644 --- a/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php +++ b/app/code/Magento/Braintree/Gateway/Response/PayPalDetailsHandler.php @@ -1,6 +1,6 @@ setAdditionalInformation(self::RISK_DATA_ID, $transaction->riskData->id); $payment->setAdditionalInformation(self::RISK_DATA_DECISION, $transaction->riskData->decision); + + // mark payment as fraud + if ($transaction->riskData->decision === self::$statusReview) { + $payment->setIsFraudDetected(true); + } } } diff --git a/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php index 42c7e67a78b9a..c4aee2ca024b3 100644 --- a/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php +++ b/app/code/Magento/Braintree/Gateway/Response/ThreeDSecureDetailsHandler.php @@ -1,6 +1,6 @@ transaction) + $response instanceof Successful + && isset($response->transaction) && in_array( $response->transaction->status, [Transaction::AUTHORIZED, Transaction::SUBMITTED_FOR_SETTLEMENT, Transaction::SETTLING] diff --git a/app/code/Magento/Braintree/Helper/CcType.php b/app/code/Magento/Braintree/Helper/CcType.php index 4ba887b996e5e..46398565abef1 100644 --- a/app/code/Magento/Braintree/Helper/CcType.php +++ b/app/code/Magento/Braintree/Helper/CcType.php @@ -1,6 +1,6 @@ collectionFactory = $factory; $this->countryConfig = $countryConfig; } @@ -52,6 +51,7 @@ public function getCountries() ->loadData() ->toOptionArray(false); } + return $this->countries; } } diff --git a/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php b/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php index 12e7cd8f532cc..c53d9e3f5ba8c 100644 --- a/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php +++ b/app/code/Magento/Braintree/Model/Adapter/BraintreeAdapter.php @@ -1,6 +1,6 @@ getMappedValues() as $key => $value) { $attribute = $this->attributeValueFactory->create(); + if(in_array($key, $shouldBeLocalized)) { + $value = __($value); + } $output[] = $attribute->setAttributeCode($key)->setValue($value); } return $output; diff --git a/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php b/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php index f52f19c0ab6f0..1b6ff84067239 100644 --- a/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php +++ b/app/code/Magento/Braintree/Model/Report/TransactionsCollection.php @@ -1,11 +1,12 @@ componentFactory = $componentFactory; + $this->urlBuilder = $urlBuilder; + $this->config = $config; + } + + /** + * @inheritdoc + */ + public function getComponentForToken(PaymentTokenInterface $paymentToken) + { + $data = json_decode($paymentToken->getTokenDetails() ?: '{}', true); + $data['icon'] = $this->config->getPayPalIcon(); + $component = $this->componentFactory->create( + [ + 'config' => [ + 'code' => PayPalConfigProvider::PAYPAL_VAULT_CODE, + 'nonceUrl' => $this->getNonceRetrieveUrl(), + TokenUiComponentProviderInterface::COMPONENT_DETAILS => $data, + TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash(), + 'template' => 'Magento_Braintree::form/paypal/vault.phtml' + ], + 'name' => Template::class + ] + ); + + return $component; + } + + /** + * Get url to retrieve payment method nonce + * @return string + */ + private function getNonceRetrieveUrl() + { + return $this->urlBuilder->getUrl(ConfigProvider::CODE . '/payment/getnonce', ['_secure' => true]); + } +} diff --git a/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php b/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php index 6cfc96ea23d0d..b2c6b53e2538a 100644 --- a/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php +++ b/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php @@ -1,6 +1,6 @@ componentFactory->create( [ 'config' => [ + 'code' => ConfigProvider::CC_VAULT_CODE, 'nonceUrl' => $this->getNonceRetrieveUrl(), TokenUiComponentProviderInterface::COMPONENT_DETAILS => $data, TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash(), diff --git a/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php b/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php index d720b748ba819..b05797a62940a 100644 --- a/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php +++ b/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php @@ -1,10 +1,11 @@ config = $config; - $this->payPalConfig = $payPalConfig; $this->adapter = $adapter; - $this->localeResolver = $localeResolver; } /** @@ -74,12 +67,10 @@ public function __construct( */ public function getConfig() { - $isPayPalActive = $this->payPalConfig->isActive(); return [ 'payment' => [ self::CODE => [ 'isActive' => $this->config->isActive(), - 'isSingleUse' => !$isPayPalActive, 'clientToken' => $this->getClientToken(), 'ccTypesMapper' => $this->config->getCctypesMapper(), 'sdkUrl' => $this->config->getSdkUrl(), @@ -90,22 +81,13 @@ public function getConfig() 'kountMerchantId' => $this->config->getKountMerchantId(), 'hasFraudProtection' => $this->config->hasFraudProtection(), 'merchantId' => $this->config->getMerchantId(), - 'ccVaultCode' => static::CC_VAULT_CODE + 'ccVaultCode' => self::CC_VAULT_CODE ], Config::CODE_3DSECURE => [ 'enabled' => $this->config->isVerify3DSecure(), 'thresholdAmount' => $this->config->getThresholdAmount(), 'specificCountries' => $this->config->get3DSecureSpecificCountries() ], - self::PAYPAL_CODE => [ - 'isActive' => $isPayPalActive, - 'title' => $this->payPalConfig->getTitle(), - 'isAllowShippingAddressOverride' => $this->payPalConfig->isAllowToEditShippingAddress(), - 'merchantName' => $this->payPalConfig->getMerchantName(), - 'locale' => strtolower($this->localeResolver->getLocale()), - 'paymentAcceptanceMarkSrc' => - 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-medium.png', - ] ] ]; } @@ -117,7 +99,14 @@ public function getConfig() public function getClientToken() { if (empty($this->clientToken)) { - $this->clientToken = $this->adapter->generate(); + $params = []; + + $merchantAccountId = $this->config->getMerchantAccountId(); + if (!empty($merchantAccountId)) { + $params[PaymentDataBuilder::MERCHANT_ACCOUNT_ID] = $merchantAccountId; + } + + $this->clientToken = $this->adapter->generate($params); } return $this->clientToken; diff --git a/app/code/Magento/Braintree/Model/Ui/PayPal/ConfigProvider.php b/app/code/Magento/Braintree/Model/Ui/PayPal/ConfigProvider.php new file mode 100644 index 0000000000000..270e0ed6e83c0 --- /dev/null +++ b/app/code/Magento/Braintree/Model/Ui/PayPal/ConfigProvider.php @@ -0,0 +1,56 @@ +config = $config; + $this->resolver = $resolver; + } + + public function getConfig() + { + return [ + 'payment' => [ + self::PAYPAL_CODE => [ + 'isActive' => $this->config->isActive(), + 'title' => $this->config->getTitle(), + 'isAllowShippingAddressOverride' => $this->config->isAllowToEditShippingAddress(), + 'merchantName' => $this->config->getMerchantName(), + 'locale' => strtolower($this->resolver->getLocale()), + 'paymentAcceptanceMarkSrc' => + 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-medium.png', + 'vaultCode' => self::PAYPAL_VAULT_CODE, + 'skipOrderReview' => $this->config->isSkipOrderReview(), + 'paymentIcon' => $this->config->getPayPalIcon(), + ] + ] + ]; + } +} diff --git a/app/code/Magento/Braintree/Model/Ui/PayPal/TokenUiComponentProvider.php b/app/code/Magento/Braintree/Model/Ui/PayPal/TokenUiComponentProvider.php new file mode 100644 index 0000000000000..5cf6db8759f48 --- /dev/null +++ b/app/code/Magento/Braintree/Model/Ui/PayPal/TokenUiComponentProvider.php @@ -0,0 +1,73 @@ +componentFactory = $componentFactory; + $this->urlBuilder = $urlBuilder; + } + + /** + * Get UI component for token + * @param PaymentTokenInterface $paymentToken + * @return TokenUiComponentInterface + */ + public function getComponentForToken(PaymentTokenInterface $paymentToken) + { + $jsonDetails = json_decode($paymentToken->getTokenDetails() ?: '{}', true); + $component = $this->componentFactory->create( + [ + 'config' => [ + 'code' => ConfigProvider::PAYPAL_VAULT_CODE, + 'nonceUrl' => $this->getNonceRetrieveUrl(), + TokenUiComponentProviderInterface::COMPONENT_DETAILS => $jsonDetails, + TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash() + ], + 'name' => 'Magento_Braintree/js/view/payment/method-renderer/paypal-vault' + ] + ); + + return $component; + } + + /** + * Get url to retrieve payment method nonce + * @return string + */ + private function getNonceRetrieveUrl() + { + return $this->urlBuilder->getUrl(CommonConfigProvider::CODE . '/payment/getnonce', ['_secure' => true]); + } +} diff --git a/app/code/Magento/Braintree/Model/Ui/TokenUiComponentProvider.php b/app/code/Magento/Braintree/Model/Ui/TokenUiComponentProvider.php index 1fe3fb24db8d8..84d17896e72fb 100644 --- a/app/code/Magento/Braintree/Model/Ui/TokenUiComponentProvider.php +++ b/app/code/Magento/Braintree/Model/Ui/TokenUiComponentProvider.php @@ -1,6 +1,6 @@ willReturnSelf(); $searchCriteria = new SearchCriteria(); - $this->searchCriteriaBuilder->expects(static::once()) + $this->searchCriteriaBuilder->expects(static::exactly(2)) ->method('addFilters') ->willReturnSelf(); $this->searchCriteriaBuilder->expects(static::once()) diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php index 9600abfcf60cf..004295e813384 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php @@ -1,6 +1,6 @@ scopeConfigMock->expects(static::at(0)) + ->method('getValue') + ->with($this->getPath('descriptor_name'), ScopeInterface::SCOPE_STORE, null) + ->willReturn($name); + $this->scopeConfigMock->expects(static::at(1)) + ->method('getValue') + ->with($this->getPath('descriptor_phone'), ScopeInterface::SCOPE_STORE, null) + ->willReturn($phone); + $this->scopeConfigMock->expects(static::at(2)) + ->method('getValue') + ->with($this->getPath('descriptor_url'), ScopeInterface::SCOPE_STORE, null) + ->willReturn($url); + + $actual = $this->model->getDynamicDescriptors(); + static::assertEquals($expected, $actual); + } + + /** + * Get variations to test dynamic descriptors + * @return array + */ + public function descriptorsDataProvider() + { + $name = 'company * product'; + $phone = '333-22-22-333'; + $url = 'https://test.url.mage.com'; + return [ + [ + $name, $phone, $url, + 'expected' => [ + 'name' => $name, 'phone' => $phone, 'url' => $url + ] + ], + [ + $name, null, null, + 'expected' => [ + 'name' => $name + ] + ], + [ + null, null, $url, + 'expected' => [ + 'url' => $url + ] + ], + [ + null, null, null, + 'expected' => [] + ] + ]; + } + /** * Return config path * diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php index 02192c819daf5..f4056c8abb3f3 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Helper/SubjectReaderTest.php @@ -1,6 +1,6 @@ config = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->setMethods(['getDynamicDescriptors']) + ->getMock(); + + $this->builder = new DescriptorDataBuilder($this->config); + } + + /** + * @covers \Magento\Braintree\Gateway\Request\DescriptorDataBuilder::build + * @param array $descriptors + * @param array $expected + * @dataProvider buildDataProvider + */ + public function testBuild(array $descriptors, array $expected) + { + $this->config->expects(static::once()) + ->method('getDynamicDescriptors') + ->willReturn($descriptors); + + $actual = $this->builder->build([]); + static::assertEquals($expected, $actual); + } + + /** + * Get variations for build method testing + * @return array + */ + public function buildDataProvider() + { + $name = 'company * product'; + $phone = '333-22-22-333'; + $url = 'https://test.url.mage.com'; + return [ + [ + 'descriptors' => [ + 'name' => $name, + 'phone' => $phone, + 'url' => $url + ], + 'expected' => [ + 'descriptor' => [ + 'name' => $name, + 'phone' => $phone, + 'url' => $url + ] + ] + ], + [ + 'descriptors' => [ + 'name' => $name, + 'phone' => $phone + ], + 'expected' => [ + 'descriptor' => [ + 'name' => $name, + 'phone' => $phone + ] + ] + ], + [ + 'descriptors' => [ + 'name' => $name + ], + 'expected' => [ + 'descriptor' => [ + 'name' => $name + ] + ] + ], + [ + 'descriptors' => [], + 'expected' => [] + ] + ]; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php index c695ad24376b3..691fbbd8c14be 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php @@ -1,6 +1,6 @@ self::DEVICE_DATA + DataAssignObserver::DEVICE_DATA => self::DEVICE_DATA ]; $expectedResult = [ diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/DeviceDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/DeviceDataBuilderTest.php new file mode 100644 index 0000000000000..226f929943504 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/DeviceDataBuilderTest.php @@ -0,0 +1,115 @@ +subjectReader = $this->getMockBuilder(SubjectReader::class) + ->disableOriginalConstructor() + ->setMethods(['readPayment']) + ->getMock(); + + $this->paymentDataObject = $this->getMock(PaymentDataObjectInterface::class); + + $this->paymentInfo = $this->getMock(InfoInterface::class); + + $this->builder = new DeviceDataBuilder($this->subjectReader); + } + + /** + * @covers \Magento\Braintree\Gateway\Request\PayPal\DeviceDataBuilder::build + * @param array $paymentData + * @param array $expected + * @dataProvider buildDataProvider + */ + public function testBuild(array $paymentData, array $expected) + { + $subject = [ + 'payment' => $this->paymentDataObject + ]; + + $this->subjectReader->expects(static::once()) + ->method('readPayment') + ->with($subject) + ->willReturn($this->paymentDataObject); + + $this->paymentDataObject->expects(static::once()) + ->method('getPayment') + ->willReturn($this->paymentInfo); + + $this->paymentInfo->expects(static::once()) + ->method('getAdditionalInformation') + ->willReturn($paymentData); + + $actual = $this->builder->build($subject); + static::assertEquals($expected, $actual); + } + + /** + * Get variations for build method testing + * @return array + */ + public function buildDataProvider() + { + return [ + [ + 'paymentData' => [ + 'device_data' => '{correlation_id: 12s3jf9as}' + ], + 'expected' => [ + 'deviceData' => '{correlation_id: 12s3jf9as}' + ] + ], + [ + 'paymentData' => [ + 'device_data' => null, + ], + 'expected' => [] + ], + [ + 'paymentData' => [ + 'deviceData' => '{correlation_id: 12s3jf9as}', + ], + 'expected' => [] + ], + [ + 'paymentData' => [], + 'expected' => [] + ] + ]; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/VaultDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/VaultDataBuilderTest.php new file mode 100644 index 0000000000000..6b5ade3ebf437 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PayPal/VaultDataBuilderTest.php @@ -0,0 +1,112 @@ +paymentDataObject = $this->getMock(PaymentDataObjectInterface::class); + + $this->paymentInfo = $this->getMock(InfoInterface::class); + + $this->subjectReader = $this->getMockBuilder(SubjectReader::class) + ->disableOriginalConstructor() + ->setMethods(['readPayment']) + ->getMock(); + + $this->builder = new VaultDataBuilder($this->subjectReader); + } + + /** + * @covers \Magento\Braintree\Gateway\Request\PayPal\VaultDataBuilder::build + * @param array $additionalInfo + * @param array $expected + * @dataProvider buildDataProvider + */ + public function testBuild(array $additionalInfo, array $expected) + { + $subject = [ + 'payment' => $this->paymentDataObject + ]; + + $this->subjectReader->expects(static::once()) + ->method('readPayment') + ->with($subject) + ->willReturn($this->paymentDataObject); + + $this->paymentDataObject->expects(static::once()) + ->method('getPayment') + ->willReturn($this->paymentInfo); + + $this->paymentInfo->expects(static::once()) + ->method('getAdditionalInformation') + ->willReturn($additionalInfo); + + $actual = $this->builder->build($subject); + static::assertEquals($expected, $actual); + } + + /** + * Get variations to test build method + * @return array + */ + public function buildDataProvider() + { + return [ + [ + 'additionalInfo' => [ + VaultConfigProvider::IS_ACTIVE_CODE => true + ], + 'expected' => [ + 'options' => [ + 'storeInVaultOnSuccess' => true + ] + ] + ], + [ + 'additionalInfo' => [ + VaultConfigProvider::IS_ACTIVE_CODE => false + ], + 'expected' => [] + ], + [ + 'additionalInfo' => [], + 'expected' => [] + ], + ]; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php index 47a9a49670eb4..40d62a64790e7 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php @@ -1,6 +1,6 @@ willReturnMap($additionalData); $this->configMock->expects(static::once()) - ->method('getValue') - ->with(Config::KEY_MERCHANT_ACCOUNT_ID) + ->method('getMerchantAccountId') ->willReturn(self::MERCHANT_ACCOUNT_ID); $this->paymentDO->expects(static::once()) diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php index 6b1b5744fb91a..bea9878966fb1 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/RefundDataBuilderTest.php @@ -1,6 +1,6 @@ getMockBuilder(OrderPaymentExtension::class) ->setMethods(['getVaultPaymentToken']) ->disableOriginalConstructor() - ->getMock(); + ->getMockForAbstractClass(); $paymentToken = $this->getMockBuilder(PaymentToken::class) ->disableOriginalConstructor() diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php index 0caf259627b42..84c14afff2358 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultDataBuilderTest.php @@ -1,6 +1,6 @@ paymentDataObject = $this->getMockForAbstractClass(PaymentDataObjectInterface::class); + + $this->paymentInfo = $this->getMockBuilder(Payment::class) + ->disableOriginalConstructor() + ->setMethods(['__wakeup']) + ->getMock(); + + $this->paymentToken = $objectManager->getObject(PaymentToken::class); + + $this->paymentTokenFactory = $this->getMockBuilder(AccountPaymentTokenFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->paymentExtension = $this->getMockBuilder(OrderPaymentExtensionInterface::class) + ->setMethods(['setVaultPaymentToken', 'getVaultPaymentToken']) + ->disableOriginalConstructor() + ->getMock(); + $this->paymentExtensionFactory = $this->getMockBuilder(OrderPaymentExtensionInterfaceFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->subject = [ + 'payment' => $this->paymentDataObject, + ]; + $this->subjectReader = $this->getMockBuilder(SubjectReader::class) + ->disableOriginalConstructor() + ->setMethods(['readPayment', 'readTransaction']) + ->getMock(); + $this->subjectReader->expects(static::once()) + ->method('readPayment') + ->with($this->subject) + ->willReturn($this->paymentDataObject); + + $this->dateTimeFactory = $this->getMockBuilder(DateTimeFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->handler = new VaultDetailsHandler( + $this->paymentTokenFactory, + $this->paymentExtensionFactory, + $this->subjectReader, + $this->dateTimeFactory + ); + } + + /** + * @covers \Magento\Braintree\Gateway\Response\PayPal\VaultDetailsHandler::handle + */ + public function testHandle() + { + /** @var Transaction $transaction */ + $transaction = $this->getTransaction(); + $response = [ + 'object' => $transaction + ]; + + $this->paymentExtension->expects(static::once()) + ->method('setVaultPaymentToken') + ->with($this->paymentToken); + $this->paymentExtension->expects(static::once()) + ->method('getVaultPaymentToken') + ->willReturn($this->paymentToken); + + $this->subjectReader->expects(static::once()) + ->method('readTransaction') + ->with($response) + ->willReturn($transaction); + + $this->paymentDataObject->expects(static::once()) + ->method('getPayment') + ->willReturn($this->paymentInfo); + + $this->paymentTokenFactory->expects(static::once()) + ->method('create') + ->willReturn($this->paymentToken); + + $this->paymentExtensionFactory->expects(static::once()) + ->method('create') + ->willReturn($this->paymentExtension); + + $dateTime = new \DateTime('2016-07-05 00:00:00', new \DateTimeZone('UTC')); + $expirationDate = '2017-07-05 00:00:00'; + $this->dateTimeFactory->expects(static::once()) + ->method('create') + ->willReturn($dateTime); + + $this->handler->handle($this->subject, $response); + + $extensionAttributes = $this->paymentInfo->getExtensionAttributes(); + /** @var PaymentTokenInterface $paymentToken */ + $paymentToken = $extensionAttributes->getVaultPaymentToken(); + static::assertNotNull($paymentToken); + + $tokenDetails = json_decode($paymentToken->getTokenDetails(), true); + + static::assertSame($this->paymentToken, $paymentToken); + static::assertEquals($transaction->paypalDetails->token, $paymentToken->getGatewayToken()); + static::assertEquals($transaction->paypalDetails->payerEmail, $tokenDetails['payerEmail']); + static::assertEquals($expirationDate, $paymentToken->getExpiresAt()); + } + + /** + * @covers \Magento\Braintree\Gateway\Response\PayPal\VaultDetailsHandler::handle + */ + public function testHandleWithoutToken() + { + $transaction = $this->getTransaction(); + $transaction->paypalDetails->token = null; + + $response = [ + 'object' => $transaction + ]; + + $this->subjectReader->expects(static::once()) + ->method('readTransaction') + ->with($response) + ->willReturn($transaction); + + $this->paymentDataObject->expects(static::once()) + ->method('getPayment') + ->willReturn($this->paymentInfo); + + $this->paymentTokenFactory->expects(static::never()) + ->method('create'); + + $this->dateTimeFactory->expects(static::never()) + ->method('create'); + + $this->handler->handle($this->subject, $response); + static::assertNull($this->paymentInfo->getExtensionAttributes()); + } + + /** + * Create Braintree transaction + * @return Transaction + */ + private function getTransaction() + { + $attributes = [ + 'id' => self::$transactionId, + 'paypalDetails' => $this->getPayPalDetails() + ]; + + $transaction = Transaction::factory($attributes); + + return $transaction; + } + + /** + * Get PayPal transaction details + * @return PayPalDetails + */ + private function getPayPalDetails() + { + $attributes = [ + 'token' => 'rc39al', + 'payerEmail' => 'john.doe@example.com' + ]; + + $details = new PayPalDetails($attributes); + + return $details; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php index b78b9ce4ff710..0726354d41b1c 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/PayPalDetailsHandlerTest.php @@ -1,6 +1,6 @@ subjectReaderMock = $this->getMockBuilder(SubjectReader::class) + $this->subjectReader = $this->getMockBuilder(SubjectReader::class) ->disableOriginalConstructor() + ->setMethods(['readPayment', 'readTransaction']) ->getMock(); - $this->riskDataHandler = new RiskDataHandler($this->subjectReaderMock); + $this->riskDataHandler = new RiskDataHandler($this->subjectReader); } /** - * Run test for handle method + * Test for handle method + * @covers \Magento\Braintree\Gateway\Response\RiskDataHandler::handle + * @param string $riskDecision + * @param boolean $isFraud + * @dataProvider riskDataProvider */ - public function testHandle() + public function testHandle($riskDecision, $isFraud) { - $paymentData = $this->getPaymentDataObjectMock(); - $transaction = $this->getBraintreeTransactionMock(); + /** @var Payment|MockObject $payment */ + $payment = $this->getMockBuilder(Payment::class) + ->disableOriginalConstructor() + ->setMethods(['setAdditionalInformation', 'setIsFraudDetected']) + ->getMock(); + /** @var PaymentDataObjectInterface|MockObject $paymentDO */ + $paymentDO = $this->getMock(PaymentDataObjectInterface::class); + $paymentDO->expects(self::once()) + ->method('getPayment') + ->willReturn($payment); + + $transaction = Transaction::factory([ + 'riskData' => [ + 'id' => 'test-id', + 'decision' => $riskDecision + ] + ]); $response = [ 'object' => $transaction ]; $handlingSubject = [ - 'payment' =>$paymentData, + 'payment' => $paymentDO, ]; - $this->subjectReaderMock->expects(self::once()) + $this->subjectReader->expects(static::once()) ->method('readPayment') ->with($handlingSubject) - ->willReturn($paymentData); - $this->subjectReaderMock->expects(self::once()) + ->willReturn($paymentDO); + $this->subjectReader->expects(static::once()) ->method('readTransaction') ->with($response) ->willReturn($transaction); - $this->riskDataHandler->handle($handlingSubject, $response); - } - - /** - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getBraintreeTransactionMock() - { - $transaction = \Braintree\Transaction::factory([]); - $transaction->_set( - 'riskData', - RiskData::factory( - [ - 'id' => 'test-id', - 'decision' => 'test-decision', - ] - ) - ); - - return $transaction; - } - - /** - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getPaymentDataObjectMock() - { - $mock = $this->getMockBuilder(PaymentDataObjectInterface::class) - ->getMockForAbstractClass(); + $payment->expects(static::at(0)) + ->method('setAdditionalInformation') + ->with(RiskDataHandler::RISK_DATA_ID, 'test-id'); + $payment->expects(static::at(1)) + ->method('setAdditionalInformation') + ->with(RiskDataHandler::RISK_DATA_DECISION, $riskDecision); - $mock->expects(static::once()) - ->method('getPayment') - ->willReturn($this->getPaymentMock()); + if (!$isFraud) { + $payment->expects(static::never()) + ->method('setIsFraudDetected'); + } else { + $payment->expects(static::once()) + ->method('setIsFraudDetected') + ->with(true); + } - return $mock; + $this->riskDataHandler->handle($handlingSubject, $response); } /** - * @return \PHPUnit_Framework_MockObject_MockObject + * Get list of variations to test fraud + * @return array */ - private function getPaymentMock() + public function riskDataProvider() { - $paymentMock = $this->getMockBuilder(Payment::class) - ->disableOriginalConstructor() - ->getMock(); - - $paymentMock->expects(self::at(0)) - ->method('setAdditionalInformation') - ->with(RiskDataHandler::RISK_DATA_ID, 'test-id'); - $paymentMock->expects(self::at(1)) - ->method('setAdditionalInformation') - ->with(RiskDataHandler::RISK_DATA_DECISION, 'test-decision'); - - return $paymentMock; + return [ + ['decision' => 'Not Evaluated', 'isFraud' => false], + ['decision' => 'Approve', 'isFraud' => false], + ['decision' => 'Review', 'isFraud' => true], + ]; } } diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php index 973f67532af9c..835f754444a5c 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php @@ -1,6 +1,6 @@ paymentToken = $this->getMock(PaymentTokenInterface::class); - $this->paymentTokenFactory = $this->getMockBuilder(PaymentTokenInterfaceFactory::class) + $this->paymentTokenFactory = $this->getMockBuilder(CreditCardTokenFactory::class) ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php index f0ec710e13827..51971e077f91a 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/VoidHandlerTest.php @@ -1,6 +1,6 @@ resultInterfaceFactoryMock = $this->getMockBuilder( - 'Magento\Payment\Gateway\Validator\ResultInterfaceFactory' + \Magento\Payment\Gateway\Validator\ResultInterfaceFactory::class )->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php index fb88dcb5f5f01..3467567f7cd62 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php @@ -1,6 +1,6 @@ resultInterfaceFactoryMock = $this->getMockBuilder( - 'Magento\Payment\Gateway\Validator\ResultInterfaceFactory' - )->disableOriginalConstructor() + $this->resultInterfaceFactory = $this->getMockBuilder(ResultInterfaceFactory::class) + ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class) + $this->subjectReader = $this->getMockBuilder(SubjectReader::class) ->disableOriginalConstructor() ->getMock(); $this->responseValidator = new ResponseValidator( - $this->resultInterfaceFactoryMock, - $this->subjectReaderMock + $this->resultInterfaceFactory, + $this->subjectReader ); } @@ -63,7 +65,7 @@ public function testValidateReadResponseException() 'response' => null ]; - $this->subjectReaderMock->expects(self::once()) + $this->subjectReader->expects(self::once()) ->method('readResponseObject') ->with($validationSubject) ->willThrowException(new \InvalidArgumentException()); @@ -80,7 +82,7 @@ public function testValidateReadResponseObjectException() 'response' => ['object' => null] ]; - $this->subjectReaderMock->expects(self::once()) + $this->subjectReader->expects(self::once()) ->method('readResponseObject') ->with($validationSubject) ->willThrowException(new \InvalidArgumentException()); @@ -100,25 +102,25 @@ public function testValidateReadResponseObjectException() */ public function testValidate(array $validationSubject, $isValid, $messages) { - /** @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject $resultMock */ - $resultMock = $this->getMock(ResultInterface::class); + /** @var ResultInterface|MockObject $result */ + $result = $this->getMock(ResultInterface::class); - $this->subjectReaderMock->expects(self::once()) + $this->subjectReader->expects(self::once()) ->method('readResponseObject') ->with($validationSubject) ->willReturn($validationSubject['response']['object']); - $this->resultInterfaceFactoryMock->expects(self::once()) + $this->resultInterfaceFactory->expects(self::once()) ->method('create') ->with([ 'isValid' => $isValid, 'failsDescription' => $messages ]) - ->willReturn($resultMock); + ->willReturn($result); - $actualMock = $this->responseValidator->validate($validationSubject); + $actual = $this->responseValidator->validate($validationSubject); - self::assertEquals($resultMock, $actualMock); + self::assertEquals($result, $actual); } /** @@ -126,19 +128,21 @@ public function testValidate(array $validationSubject, $isValid, $messages) */ public function dataProviderTestValidate() { - $successTrue = new \stdClass(); + $successTrue = new Successful(); $successTrue->success = true; $successTrue->transaction = new \stdClass(); $successTrue->transaction->status = Transaction::AUTHORIZED; - $successFalse = new \stdClass(); + $successFalse = new Successful(); $successFalse->success = false; - $transactionDeclined = new \stdClass(); + $transactionDeclined = new Successful(); $transactionDeclined->success = true; $transactionDeclined->transaction = new \stdClass(); $transactionDeclined->transaction->status = Transaction::SETTLEMENT_DECLINED; + $errorResult = new Error(['errors' => []]); + return [ [ 'validationSubject' => [ @@ -171,6 +175,18 @@ public function dataProviderTestValidate() [ __('Wrong transaction status') ] + ], + [ + 'validationSubject' => [ + 'response' => [ + 'object' => $errorResult, + ] + ], + 'isValid' => false, + [ + __('Braintree error response.'), + __('Wrong transaction status') + ] ] ]; } diff --git a/app/code/Magento/Braintree/Test/Unit/Helper/CcTypeTest.php b/app/code/Magento/Braintree/Test/Unit/Helper/CcTypeTest.php index e4f17946b2d92..b82c5b9eade99 100644 --- a/app/code/Magento/Braintree/Test/Unit/Helper/CcTypeTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Helper/CcTypeTest.php @@ -1,6 +1,6 @@ setMethods(['create']) ->disableOriginalConstructor() ->getMock(); + $this->defaultRenderer = Phrase::getRenderer(); + $this->rendererMock = $this->getMockBuilder(RendererInterface::class) + ->getMock(); } /** @@ -65,6 +80,8 @@ public function testGetCustomAttributes($transaction) $this->transactionStub ); + Phrase::setRenderer($this->rendererMock); + /** @var AttributeValue[] $result */ $result = $map->getCustomAttributes(); @@ -77,6 +94,31 @@ public function testGetCustomAttributes($transaction) $result[6]->getValue() ); $this->assertEquals(implode(', ', $transaction['refundIds']), $result[11]->getValue()); + $this->assertEquals($transaction['merchantAccountId'], $result[1]->getValue()); + $this->assertEquals($transaction['orderId'], $result[2]->getValue()); + $this->assertEquals($transaction['amount'], $result[7]->getValue()); + $this->assertEquals($transaction['processorSettlementResponseCode'], $result[8]->getValue()); + $this->assertEquals($transaction['processorSettlementResponseText'], $result[10]->getValue()); + $this->assertEquals($transaction['settlementBatchId'], $result[12]->getValue()); + $this->assertEquals($transaction['currencyIsoCode'], $result[13]->getValue()); + + $this->rendererMock->expects($this->at(0)) + ->method('render') + ->with([$transaction['paymentInstrumentType']]) + ->willReturn('Credit card'); + $this->assertEquals('Credit card', $result[3]->getValue()->render()); + + $this->rendererMock->expects($this->at(0)) + ->method('render') + ->with([$transaction['type']]) + ->willReturn('Sale'); + $this->assertEquals('Sale', $result[5]->getValue()->render()); + + $this->rendererMock->expects($this->at(0)) + ->method('render') + ->with([$transaction['status']]) + ->willReturn('Pending for settlement'); + $this->assertEquals('Pending for settlement', $result[9]->getValue()->render()); } /** @@ -90,9 +132,27 @@ public function getConfigDataProvider() 'id' => 1, 'createdAt' => new \DateTime(), 'paypalDetails' => new PayPalDetails(['paymentId' => 10]), - 'refundIds' => [1, 2, 3, 4, 5] + 'refundIds' => [1, 2, 3, 4, 5], + 'merchantAccountId' => 'MerchantId', + 'orderId' => 1, + 'paymentInstrumentType' => 'credit_card', + 'type' => 'sale', + 'amount' => '$19.99', + 'processorSettlementResponseCode' => 1, + 'status' => 'pending_for_settlement', + 'processorSettlementResponseText' => 'sample text', + 'settlementBatchId' => 2, + 'currencyIsoCode' => 'USD' ] ] ]; } + + /** + * @return void + */ + protected function tearDown() + { + Phrase::setRenderer($this->defaultRenderer); + } } diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php index 50488df2600c6..7ceaadf40e644 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/Report/TransactionsCollectionTest.php @@ -1,6 +1,6 @@ assertEquals(TransactionsCollection::TRANSACTION_MAXIMUM_COUNT, count($items)); $this->assertInstanceOf(DocumentInterface::class, $items[1]); } + + /** + * Add fields to filter + * + * @dataProvider addToFilterDataProvider + */ + public function testAddToFilter($field, $condition, $filterMapperCall, $expectedCondition) + { + $this->filterMapperMock->expects(static::exactly($filterMapperCall)) + ->method('getFilter') + ->with($field, $expectedCondition) + ->willReturn(new BraintreeSearchNodeStub()); + + $collection = new TransactionsCollection( + $this->entityFactoryMock, + $this->braintreeAdapterMock, + $this->filterMapperMock + ); + + static::assertInstanceOf( + TransactionsCollection::class, + $collection->addFieldToFilter($field, $condition) + ); + } + + /** + * addToFilter DataProvider + * + * @return array + */ + public function addToFilterDataProvider() + { + return [ + ['orderId', ['like' => 1], 1, ['like' => 1]], + ['type', 'sale', 1, ['eq' => 'sale']], + [['type', 'orderId'], [], 0, []], + ]; + } } diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php new file mode 100644 index 0000000000000..8902b1ee08fc0 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php @@ -0,0 +1,114 @@ +componentFactory = $this->getMockBuilder(TokenUiComponentInterfaceFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->urlBuilder = $this->getMock(UrlInterface::class); + + $this->config = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->setMethods(['getPayPalIcon']) + ->getMock(); + + $this->tokenUiComponentProvider = new TokenUiComponentProvider( + $this->componentFactory, + $this->urlBuilder, + $this->config + ); + } + + /** + * @covers \Magento\Braintree\Model\Ui\Adminhtml\PayPal\TokenUiComponentProvider::getComponentForToken + */ + public function testGetComponentForToken() + { + $nonceUrl = 'https://payment/adminhtml/nonce/url'; + $payerEmail = 'john.doe@test.com'; + $icon = [ + 'url' => 'https://payment/adminhtml/icon.png', + 'width' => 48, + 'height' => 32 + ]; + + $expected = [ + 'code' => 'vault', + 'nonceUrl' => $nonceUrl, + 'details' => [ + 'payerEmail' => $payerEmail, + 'icon' => $icon + ], + 'template' => 'vault.phtml' + ]; + + $this->config->expects(static::once()) + ->method('getPayPalIcon') + ->willReturn($icon); + + $paymentToken = $this->getMock(PaymentTokenInterface::class); + $paymentToken->expects(static::once()) + ->method('getTokenDetails') + ->willReturn('{"payerEmail":" ' . $payerEmail . '"}'); + $paymentToken->expects(static::once()) + ->method('getPublicHash') + ->willReturn('cmk32dl21l'); + + $this->urlBuilder->expects(static::once()) + ->method('getUrl') + ->willReturn($nonceUrl); + + $tokenComponent = $this->getMock(TokenUiComponentInterface::class); + $tokenComponent->expects(static::once()) + ->method('getConfig') + ->willReturn($expected); + + $this->componentFactory->expects(static::once()) + ->method('create') + ->willReturn($tokenComponent); + + $component = $this->tokenUiComponentProvider->getComponentForToken($paymentToken); + static::assertEquals($tokenComponent, $component); + static::assertEquals($expected, $component->getConfig()); + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php index d1665c71804cf..d39cd32425013 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php @@ -1,16 +1,16 @@ 'vault', 'nonceUrl' => $nonceUrl, 'details' => [ 'type' => $type, diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php index a787111fa93aa..4e13232533a31 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php @@ -1,6 +1,6 @@ disableOriginalConstructor() ->getMock(); - $this->payPalConfig = $this->getMockBuilder(PayPalConfig::class) + $payPalConfig = $this->getMockBuilder(PayPalConfig::class) ->disableOriginalConstructor() ->getMock(); @@ -61,13 +52,13 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->localeResolver = $this->getMockForAbstractClass(ResolverInterface::class); + $localeResolver = $this->getMockForAbstractClass(ResolverInterface::class); $this->configProvider = new ConfigProvider( $this->config, - $this->payPalConfig, + $payPalConfig, $this->braintreeAdapter, - $this->localeResolver + $localeResolver ); } @@ -90,36 +81,22 @@ public function testGetConfig($config, $expected) ->willReturn($value); } - $this->payPalConfig->expects(static::once()) - ->method('isActive') - ->willReturn(true); - - $this->payPalConfig->expects(static::once()) - ->method('isAllowToEditShippingAddress') - ->willReturn(true); - - $this->payPalConfig->expects(static::once()) - ->method('getMerchantName') - ->willReturn('Test'); - - $this->payPalConfig->expects(static::once()) - ->method('getTitle') - ->willReturn('Payment Title'); - - $this->localeResolver->expects(static::once()) - ->method('getLocale') - ->willReturn('en_US'); - static::assertEquals($expected, $this->configProvider->getConfig()); } /** * @covers \Magento\Braintree\Model\Ui\ConfigProvider::getClientToken + * @dataProvider getClientTokenDataProvider */ - public function testGetClientToken() + public function testGetClientToken($merchantAccountId, $params) { + $this->config->expects(static::once()) + ->method('getMerchantAccountId') + ->willReturn($merchantAccountId); + $this->braintreeAdapter->expects(static::once()) ->method('generate') + ->with($params) ->willReturn(self::CLIENT_TOKEN); static::assertEquals(self::CLIENT_TOKEN, $this->configProvider->getClientToken()); @@ -154,7 +131,6 @@ public function getConfigDataProvider() 'payment' => [ ConfigProvider::CODE => [ 'isActive' => true, - 'isSingleUse' => false, 'clientToken' => self::CLIENT_TOKEN, 'ccTypesMapper' => ['visa' => 'VI', 'american-express' => 'AE'], 'sdkUrl' => self::SDK_URL, @@ -174,19 +150,27 @@ public function getConfigDataProvider() 'enabled' => true, 'thresholdAmount' => 20, 'specificCountries' => ['GB', 'US', 'CA'] - ], - ConfigProvider::PAYPAL_CODE => [ - 'isActive' => true, - 'title' => 'Payment Title', - 'isAllowShippingAddressOverride' => true, - 'merchantName' => 'Test', - 'locale' => 'en_us', - 'paymentAcceptanceMarkSrc' => - 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-medium.png' ] ] ] ] ]; } + + /** + * @return array + */ + public function getClientTokenDataProvider() + { + return [ + [ + 'merchantAccountId' => '', + 'params' => [] + ], + [ + 'merchantAccountId' => self::MERCHANT_ACCOUNT_ID, + 'params' => ['merchantAccountId' => self::MERCHANT_ACCOUNT_ID] + ] + ]; + } } diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/PayPal/ConfigProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/PayPal/ConfigProviderTest.php new file mode 100644 index 0000000000000..ee7fefa6d2b09 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/PayPal/ConfigProviderTest.php @@ -0,0 +1,118 @@ +config = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->localeResolver = $this->getMockForAbstractClass(ResolverInterface::class); + + $this->configProvider = new ConfigProvider( + $this->config, + $this->localeResolver + ); + } + + /** + * Run test getConfig method + * + * @param array $config + * @dataProvider getConfigDataProvider + */ + public function testGetConfig($expected) + { + $this->config->expects(static::once()) + ->method('isActive') + ->willReturn(true); + + $this->config->expects(static::once()) + ->method('isAllowToEditShippingAddress') + ->willReturn(true); + + $this->config->expects(static::once()) + ->method('getMerchantName') + ->willReturn('Test'); + + $this->config->expects(static::once()) + ->method('getTitle') + ->willReturn('Payment Title'); + + $this->localeResolver->expects(static::once()) + ->method('getLocale') + ->willReturn('en_US'); + + $this->config->expects(static::once()) + ->method('isSkipOrderReview') + ->willReturn(false); + + $this->config->expects(static::once()) + ->method('getPayPalIcon') + ->willReturn([ + 'width' => 30, 'height' => 26, 'url' => 'https://icon.test.url' + ]); + + static::assertEquals($expected, $this->configProvider->getConfig()); + } + + /** + * @return array + */ + public function getConfigDataProvider() + { + return [ + [ + 'expected' => [ + 'payment' => [ + ConfigProvider::PAYPAL_CODE => [ + 'isActive' => true, + 'title' => 'Payment Title', + 'isAllowShippingAddressOverride' => true, + 'merchantName' => 'Test', + 'locale' => 'en_us', + 'paymentAcceptanceMarkSrc' => + 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-medium.png', + 'vaultCode' => ConfigProvider::PAYPAL_VAULT_CODE, + 'skipOrderReview' => false, + 'paymentIcon' => [ + 'width' => 30, 'height' => 26, 'url' => 'https://icon.test.url' + ] + ] + ] + ] + ] + ]; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/PayPal/TokenUiComponentProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/PayPal/TokenUiComponentProviderTest.php new file mode 100644 index 0000000000000..513704a14d5b8 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/PayPal/TokenUiComponentProviderTest.php @@ -0,0 +1,92 @@ +componentFactory = $this->getMockBuilder(TokenUiComponentInterfaceFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->tokenComponent = $this->getMockForAbstractClass(TokenUiComponentInterface::class); + + $this->urlBuilder = $this->getMockForAbstractClass(UrlInterface::class); + + $this->paymentToken = $this->getMockForAbstractClass(PaymentTokenInterface::class); + + $this->componentProvider = new TokenUiComponentProvider( + $this->componentFactory, + $this->urlBuilder + ); + } + + /** + * @covers \Magento\Braintree\Model\Ui\PayPal\TokenUiComponentProvider::getComponentForToken + */ + public function testGetComponentForToken() + { + $tokenDetails = [ + 'payerEmail' => 'john.doe@example.com' + ]; + $hash = '4g1mn4ew0vj23n2jf'; + + $this->paymentToken->expects(static::once()) + ->method('getTokenDetails') + ->willReturn(json_encode($tokenDetails)); + + $this->componentFactory->expects(static::once()) + ->method('create') + ->willReturn($this->tokenComponent); + + $this->paymentToken->expects(static::once()) + ->method('getPublicHash') + ->willReturn($hash); + + $this->urlBuilder->expects(static::once()) + ->method('getUrl'); + + $actual = $this->componentProvider->getComponentForToken($this->paymentToken); + static::assertEquals($this->tokenComponent, $actual); + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Observer/AddPaypalShortcutsTest.php b/app/code/Magento/Braintree/Test/Unit/Observer/AddPaypalShortcutsTest.php index c814de6468b77..1d72a70a7330b 100644 --- a/app/code/Magento/Braintree/Test/Unit/Observer/AddPaypalShortcutsTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Observer/AddPaypalShortcutsTest.php @@ -1,6 +1,6 @@ contextMock = $this->getMockForAbstractClass(ContextInterface::class); + $processor = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponent\Processor::class) + ->disableOriginalConstructor() + ->getMock(); + $this->contextMock->expects(static::any()) + ->method('getProcessor') + ->willReturn($processor); + $this->uiComponentFactory = $this->getMockBuilder(UiComponentFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->filterBuilderMock = $this->getMockBuilder(FilterBuilder::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->filterModifierMock = $this->getMockBuilder(FilterModifier::class) + ->setMethods(['applyFilterModifier']) + ->disableOriginalConstructor() + ->getMock(); + + $this->dataProviderMock = $this->getMockForAbstractClass(DataProviderInterface::class); + } + + /** + * Run test prepare method + * + * @param string $name + * @param array $filterData + * @param array|null $expectedCondition + * @dataProvider getPrepareDataProvider + * @return void + */ + public function testPrepare($name, $filterData, $expectedCondition) + { + /** @var FormDate PHPUnit_Framework_MockObject_MockObject|$uiComponent */ + $uiComponent = $this->getMockBuilder(FormDate::class) + ->disableOriginalConstructor() + ->getMock(); + + $uiComponent->expects($this->any()) + ->method('getContext') + ->willReturn($this->contextMock); + + $this->contextMock->expects($this->any()) + ->method('getNamespace') + ->willReturn(DateRange::NAME); + $this->contextMock->expects($this->any()) + ->method('addComponentDefinition') + ->with(DateRange::NAME, ['extends' => DateRange::NAME]); + + $this->contextMock->expects($this->any()) + ->method('getFiltersParams') + ->willReturn($filterData); + + $this->contextMock->expects($this->any()) + ->method('getDataProvider') + ->willReturn($this->dataProviderMock); + + if ($expectedCondition !== null) { + if (is_string($filterData[$name])) { + $uiComponent->expects(static::once()) + ->method('convertDate') + ->with($filterData[$name]) + ->willReturn(new \DateTime($filterData[$name], new \DateTimeZone('UTC'))); + } else { + $uiComponent->method('convertDate') + ->willReturnMap([ + [ + $filterData[$name]['from'], 0, 0, 0, + new \DateTime($filterData[$name]['from'], new \DateTimeZone('UTC')) + ], + [ + $filterData[$name]['to'], 23, 59, 59, + new \DateTime($filterData[$name]['to'] . ' 23:59:00', new \DateTimeZone('UTC')) + ], + ]); + } + + $i=0; + switch (true) { + case is_string($filterData[$name]): + case isset($filterData[$name]['from']) && !isset($filterData[$name]['to']): + case !isset($filterData[$name]['from']) && isset($filterData[$name]['to']): + $filterMock = $this->getFilterMock( + $name, + $expectedCondition['type'], + $expectedCondition['date'], + $i + ); + $this->dataProviderMock->expects(static::once()) + ->method('addFilter') + ->with($filterMock); + break; + case isset($filterData[$name]['from']) && isset($filterData[$name]['to']): + $this->getFilterMock( + $name, + $expectedCondition['type_from'], + $expectedCondition['date_from'], + $i + ); + $filterMock = $this->getFilterMock( + $name, + $expectedCondition['type_to'], + $expectedCondition['date_to'], + $i + ); + $this->dataProviderMock->expects(static::exactly(2)) + ->method('addFilter') + ->with($filterMock); + break; + } + } + + $this->uiComponentFactory->expects($this->any()) + ->method('create') + ->with($name, DateRange::COMPONENT, ['context' => $this->contextMock]) + ->willReturn($uiComponent); + + $date = new DateRange( + $this->contextMock, + $this->uiComponentFactory, + $this->filterBuilderMock, + $this->filterModifierMock, + [], + ['name' => $name] + ); + $date->prepare(); + } + + /** + * Gets Filter mock + * + * @param string $name + * @param string $expectedType + * @param string $expectedDate + * @param int $i + * + * @return Filter|\PHPUnit_Framework_MockObject_MockObject + */ + private function getFilterMock($name, $expectedType, $expectedDate, &$i) + { + $this->filterBuilderMock->expects(static::at($i++)) + ->method('setConditionType') + ->with($expectedType) + ->willReturnSelf(); + $this->filterBuilderMock->expects(static::at($i++)) + ->method('setField') + ->with($name) + ->willReturnSelf(); + $this->filterBuilderMock->expects(static::at($i++)) + ->method('setValue') + ->with($expectedDate) + ->willReturnSelf(); + + $filterMock = $this->getMock(Filter::class); + $this->filterBuilderMock->expects(static::at($i++)) + ->method('create') + ->willReturn($filterMock); + + return $filterMock; + } + + /** + * @return array + */ + public function getPrepareDataProvider() + { + return [ + [ + 'test_date', + ['test_date' => ['from' => '11-05-2015', 'to' => null]], + ['date' => '2015-05-11T00:00:00+0000', 'type' => 'gteq'], + ], + [ + 'test_date', + ['test_date' => ['from' => null, 'to' => '11-05-2015']], + ['date' => '2015-05-11T23:59:00+0000', 'type' => 'lteq'], + ], + [ + 'test_date', + ['test_date' => ['from' => '11-05-2015', 'to' => '11-05-2015']], + [ + 'date_from' => '2015-05-11T00:00:00+0000', 'type_from' => 'gteq', + 'date_to' => '2015-05-11T23:59:00+0000', 'type_to' => 'lteq' + ], + ], + [ + 'test_date', + ['test_date' => '11-05-2015'], + ['date' => '2015-05-11T00:00:00+0000', 'type' => 'eq'], + ], + [ + 'test_date', + ['test_date' => ['from' => '', 'to' => '']], + null, + ] + ]; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Ui/Component/Report/Listing/Column/CheckColumnOptionSourceTest.php b/app/code/Magento/Braintree/Test/Unit/Ui/Component/Report/Listing/Column/CheckColumnOptionSourceTest.php index d100473b2ce8e..123bf23f00a39 100644 --- a/app/code/Magento/Braintree/Test/Unit/Ui/Component/Report/Listing/Column/CheckColumnOptionSourceTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Ui/Component/Report/Listing/Column/CheckColumnOptionSourceTest.php @@ -1,6 +1,6 @@ __('Paypal account'), - PaymentInstrumentType::COINBASE_ACCOUNT => __('Coinbase account'), - PaymentInstrumentType::EUROPE_BANK_ACCOUNT => __('Europe bank account'), - PaymentInstrumentType::CREDIT_CARD => __('Credit card'), - PaymentInstrumentType::APPLE_PAY_CARD => __('Apple pay card'), - PaymentInstrumentType::ANDROID_PAY_CARD => __('Android pay card') + PaymentInstrumentType::PAYPAL_ACCOUNT => __(PaymentInstrumentType::PAYPAL_ACCOUNT), + PaymentInstrumentType::COINBASE_ACCOUNT => __(PaymentInstrumentType::COINBASE_ACCOUNT), + PaymentInstrumentType::EUROPE_BANK_ACCOUNT => __(PaymentInstrumentType::EUROPE_BANK_ACCOUNT), + PaymentInstrumentType::CREDIT_CARD => __(PaymentInstrumentType::CREDIT_CARD), + PaymentInstrumentType::APPLE_PAY_CARD => __(PaymentInstrumentType::APPLE_PAY_CARD), + PaymentInstrumentType::ANDROID_PAY_CARD => __(PaymentInstrumentType::ANDROID_PAY_CARD) ]; } } diff --git a/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/Status.php b/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/Status.php index f5424c6dd9b7f..b58bda418874f 100644 --- a/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/Status.php +++ b/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/Status.php @@ -1,6 +1,6 @@ __('Authorization expired'), - Transaction::AUTHORIZING => __('Authorizing'), - Transaction::AUTHORIZED => __('Authorized'), - Transaction::GATEWAY_REJECTED => __('Gateway rejected'), - Transaction::FAILED => __('Failed'), - Transaction::PROCESSOR_DECLINED => __('Processor declined'), - Transaction::SETTLED => __('Settled'), - Transaction::SETTLING => __('Settling'), - Transaction::SUBMITTED_FOR_SETTLEMENT => __('Submitted for settlement'), - Transaction::VOIDED => __('Voided'), - Transaction::UNRECOGNIZED => __('Unrecognized'), - Transaction::SETTLEMENT_DECLINED => __('Settlement declined'), - Transaction::SETTLEMENT_PENDING => __('Settlement pending'), - Transaction::SETTLEMENT_CONFIRMED => __('Settlement confirmed') + Transaction::AUTHORIZATION_EXPIRED => __(Transaction::AUTHORIZATION_EXPIRED), + Transaction::AUTHORIZING => __(Transaction::AUTHORIZING), + Transaction::AUTHORIZED => __(Transaction::AUTHORIZED), + Transaction::GATEWAY_REJECTED => __(Transaction::GATEWAY_REJECTED), + Transaction::FAILED => __(Transaction::FAILED), + Transaction::PROCESSOR_DECLINED => __(Transaction::PROCESSOR_DECLINED), + Transaction::SETTLED => __(Transaction::SETTLED), + Transaction::SETTLING => __(Transaction::SETTLING), + Transaction::SUBMITTED_FOR_SETTLEMENT => __(Transaction::SUBMITTED_FOR_SETTLEMENT), + Transaction::VOIDED => __(Transaction::VOIDED), + Transaction::UNRECOGNIZED => __(Transaction::UNRECOGNIZED), + Transaction::SETTLEMENT_DECLINED => __(Transaction::SETTLEMENT_DECLINED), + Transaction::SETTLEMENT_PENDING => __(Transaction::SETTLEMENT_PENDING), + Transaction::SETTLEMENT_CONFIRMED => __(Transaction::SETTLEMENT_CONFIRMED) ]; } } diff --git a/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/TransactionType.php b/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/TransactionType.php index 312b2f518b464..46c497c8eca4a 100644 --- a/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/TransactionType.php +++ b/app/code/Magento/Braintree/Ui/Component/Report/Listing/Column/TransactionType.php @@ -1,6 +1,6 @@ __('Sale'), - Transaction::CREDIT => __('Credit') + Transaction::SALE => __(Transaction::SALE), + Transaction::CREDIT => __(Transaction::CREDIT) ]; } } diff --git a/app/code/Magento/Braintree/composer.json b/app/code/Magento/Braintree/composer.json index c732c4f924e45..8ef110c99e56b 100644 --- a/app/code/Magento/Braintree/composer.json +++ b/app/code/Magento/Braintree/composer.json @@ -2,7 +2,7 @@ "name": "magento/module-braintree", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/framework": "100.1.*", "magento/magento-composer-installer": "*", "magento/module-config": "100.1.*", @@ -11,19 +11,20 @@ "magento/module-checkout": "100.1.*", "magento/module-sales": "100.1.*", "magento/module-backend": "100.1.*", - "magento/module-vault": "100.1.*", + "magento/module-vault": "100.2.*", "magento/module-customer": "100.1.*", "magento/module-catalog": "101.0.*", "magento/module-quote": "100.1.*", "magento/module-paypal": "100.1.*", "magento/module-theme": "100.1.*", + "magento/module-ui": "100.1.*", "braintree/braintree_php": "3.7.0" }, "suggest": { "magento/module-checkout-agreements": "100.1.*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.6", "license": [ "proprietary" ], diff --git a/app/code/Magento/Braintree/etc/acl.xml b/app/code/Magento/Braintree/etc/acl.xml index e926613a18e1e..49ab7740cb319 100644 --- a/app/code/Magento/Braintree/etc/acl.xml +++ b/app/code/Magento/Braintree/etc/acl.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/etc/adminhtml/di.xml b/app/code/Magento/Braintree/etc/adminhtml/di.xml index ed52db8cf7234..c91b4edbd2e70 100644 --- a/app/code/Magento/Braintree/etc/adminhtml/di.xml +++ b/app/code/Magento/Braintree/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ @@ -27,6 +27,7 @@ Magento\Braintree\Gateway\Request\ChannelDataBuilder Magento\Braintree\Gateway\Request\AddressDataBuilder Magento\Braintree\Gateway\Request\VaultDataBuilder + Magento\Braintree\Gateway\Request\DescriptorDataBuilder @@ -37,6 +38,7 @@ Magento\Braintree\Gateway\Request\PaymentDataBuilder Magento\Braintree\Gateway\Request\ChannelDataBuilder Magento\Braintree\Gateway\Request\AddressDataBuilder + Magento\Braintree\Gateway\Request\DescriptorDataBuilder @@ -45,6 +47,7 @@ Magento\Braintree\Model\Ui\Adminhtml\TokenUiComponentProvider + Magento\Braintree\Model\Ui\Adminhtml\PayPal\TokenUiComponentProvider diff --git a/app/code/Magento/Braintree/etc/adminhtml/menu.xml b/app/code/Magento/Braintree/etc/adminhtml/menu.xml index ed73aa20cdb6f..43d12aa0bb995 100644 --- a/app/code/Magento/Braintree/etc/adminhtml/menu.xml +++ b/app/code/Magento/Braintree/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/etc/adminhtml/routes.xml b/app/code/Magento/Braintree/etc/adminhtml/routes.xml index 698664f02e6a3..0991aef948541 100644 --- a/app/code/Magento/Braintree/etc/adminhtml/routes.xml +++ b/app/code/Magento/Braintree/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/etc/adminhtml/system.xml b/app/code/Magento/Braintree/etc/adminhtml/system.xml index 3668cd7779fda..4c7f46268548d 100644 --- a/app/code/Magento/Braintree/etc/adminhtml/system.xml +++ b/app/code/Magento/Braintree/etc/adminhtml/system.xml @@ -1,23 +1,21 @@

- - - - 1 - complex braintree-section - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group - - + + + + No setup or monthly fees and your customers never leave your store to complete the purchase.]]> + complex braintree-section Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment payment/braintree/active + recommended_solutions Magento\Config\Model\Config\Source\Yesno @@ -35,15 +33,19 @@ - + Magento\Config\Model\Config\Source\Yesno payment/braintree_cc_vault/active + + http://docs.magento.com/m2/ce/user_guide/payment/braintree.html + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint + - Click here to login to your existing Braintree account. Or to setup a new account and accept payments on your website, click here to signup for a Braintree account.]]> + Click here to login to your existing Braintree account. Or to setup a new account and accept payments on your website, click here to signup for a Braintree account.

Powered by Braintree v.zero with Hosted Fields latest technology. Hosted Fields are small, transparent iframes that replace the sensitive credit card inputs in your checkout flow - helping you meet the latest data security requirements while ensuring your customization doesn't suffer. Find out more.]]>
1 Magento\Config\Block\System\Config\Form\Fieldset @@ -153,6 +155,14 @@ payment/braintree_paypal/title It is recommended to set this value to "PayPal" per store views. + + + Magento\Config\Model\Config\Source\Yesno + payment/braintree_paypal_vault/active + + + + validate-number @@ -200,6 +210,11 @@ payment/braintree_paypal/display_on_shopping_cart Also affects mini-shopping cart. + + + Magento\Config\Model\Config\Source\Yesno + payment/braintree_paypal/skip_order_review +
@@ -225,6 +240,36 @@ payment/braintree/verify_specific_countries + + + Braintree Support.]]> + Magento\Config\Block\System\Config\Form\Fieldset + + + payment/braintree/descriptor_name + + The value in the business name field of a customer's statement. Company name/DBA section must be either 3, 7 or 12 characters + and the product descriptor can be up to 18, 14, or 9 characters respectively (with an * in between for a total descriptor name of 22 characters). + + + + + payment/braintree/descriptor_phone + + The value in the phone number field of a customer's statement. Phone must be 10-14 characters and can only contain numbers, dashes, parentheses and periods. + + + + + payment/braintree/descriptor_url + + The value in the URL/web address field of a customer's statement. The URL must be 13 characters or shorter. + + +
diff --git a/app/code/Magento/Braintree/etc/config.xml b/app/code/Magento/Braintree/etc/config.xml index 7511ec2ca1563..eaa233da109ce 100644 --- a/app/code/Magento/Braintree/etc/config.xml +++ b/app/code/Magento/Braintree/etc/config.xml @@ -1,7 +1,7 @@ @@ -25,13 +25,16 @@ 1 1 1 + 1 + 1 + 1 AE,VI,MC,DI,JCB,CUP,DN,MI 1 processing sandbox 0 - + cvv,number @@ -57,6 +60,8 @@ 1 1 1 + 1 + 1 processorResponseCode,processorResponseText,paymentId processorResponseCode,processorResponseText,paymentId,payerEmail @@ -64,6 +69,11 @@ BraintreeCreditCardVaultFacade Stored Cards (Braintree) + + BraintreePayPalVaultFacade + Stored Accounts (Braintree PayPal) + 1 + diff --git a/app/code/Magento/Braintree/etc/di.xml b/app/code/Magento/Braintree/etc/di.xml index def12ff4c8a7e..6f596cc4a8daf 100644 --- a/app/code/Magento/Braintree/etc/di.xml +++ b/app/code/Magento/Braintree/etc/di.xml @@ -1,7 +1,7 @@ @@ -19,13 +19,15 @@ - Magento\Braintree\Model\Ui\ConfigProvider::PAYPAL_CODE + Magento\Braintree\Model\Ui\PayPal\ConfigProvider::PAYPAL_CODE BraintreePayPalInfo BraintreePayPalValueHandlerPool + BraintreePayPalValidatorPool BraintreePayPalCommandPool - + + Magento\Braintree\Model\Ui\ConfigProvider::CC_VAULT_CODE @@ -51,6 +53,32 @@ Magento\Braintree\Model\Ui\ConfigProvider::CC_VAULT_CODE + + + Magento\Braintree\Model\Ui\PayPal\ConfigProvider::PAYPAL_VAULT_CODE + + + + + BraintreePayPalVaultPaymentConfig + + + + + + BraintreePayPalVaultPaymentValueHandler + + + + + + BraintreePayPalVaultPaymentConfig + BraintreePayPalVaultPaymentValueHandlerPool + BraintreePayPalFacade + Magento\Braintree\Model\Ui\PayPal\ConfigProvider::PAYPAL_VAULT_CODE + + + @@ -60,7 +88,7 @@ - Magento\Braintree\Model\Ui\ConfigProvider::PAYPAL_CODE + Magento\Braintree\Model\Ui\PayPal\ConfigProvider::PAYPAL_CODE @@ -70,6 +98,27 @@ Magento\Braintree\Gateway\Config\Config + + + BraintreeLoggerForTransactionSale + + + + + BraintreeLoggerForTransactionSale + + + + + BraintreeLoggerForTransactionSale + + + + + BraintreeLoggerForTransactionSale + + + @@ -85,6 +134,7 @@ BraintreeVoidCommand BraintreeRefundCommand BraintreeVoidCommand + BraintreeVoidCommand @@ -95,39 +145,49 @@ BraintreePayPalSaleCommand BraintreePayPalCaptureStrategyCommand BraintreeCaptureCommand + BraintreePayPalVaultAuthorizeCommand + BraintreePayPalVaultSaleCommand + BraintreeVaultCaptureCommand BraintreeVoidCommand BraintreeRefundCommand BraintreeVoidCommand - - + BraintreeCommandPool - - + - - BraintreeCommandManager - + BraintreePayPalCommandPool - + + - + + BraintreeCommandPool - + BraintreePayPalCommandPool + + + + BraintreeCommandManager + BraintreePayPalCommandManager + + + + - + BraintreeAuthorizeRequest @@ -146,11 +206,42 @@ Magento\Braintree\Gateway\Request\AddressDataBuilder Magento\Braintree\Gateway\Request\VaultDataBuilder Magento\Braintree\Gateway\Request\ThreeDSecureDataBuilder - Magento\Braintree\Gateway\Request\KountPaymentDataBuilder + Magento\Braintree\Gateway\Request\KountPaymentDataBuilder + Magento\Braintree\Gateway\Request\DescriptorDataBuilder + + + + + + + BraintreeSaleRequest + + + + + + BraintreeAuthorizeRequest + Magento\Braintree\Gateway\Request\SettlementDataBuilder + + + + + + + BraintreeCaptureRequest + Magento\Braintree\Gateway\Http\TransferFactory + Magento\Braintree\Gateway\Http\Client\TransactionSubmitForSettlement + Magento\Braintree\Gateway\Response\TransactionIdHandler + Magento\Braintree\Gateway\Validator\ResponseValidator + + + + + + Magento\Braintree\Gateway\Request\CaptureDataBuilder - @@ -169,74 +260,61 @@ Magento\Braintree\Gateway\Request\ChannelDataBuilder Magento\Braintree\Gateway\Request\AddressDataBuilder Magento\Braintree\Gateway\Request\ThreeDSecureDataBuilder - Magento\Braintree\Gateway\Request\KountPaymentDataBuilder + Magento\Braintree\Gateway\Request\KountPaymentDataBuilder + Magento\Braintree\Gateway\Request\DescriptorDataBuilder - - - + + - BraintreePayPalAuthorizeRequest - BraintreePayPalResponseHandler + BraintreeVaultSaleRequest - + - Magento\Braintree\Gateway\Request\CustomerDataBuilder - Magento\Braintree\Gateway\Request\PaymentDataBuilder - Magento\Braintree\Gateway\Request\ChannelDataBuilder + BraintreeVaultAuthorizeRequest + Magento\Braintree\Gateway\Request\SettlementDataBuilder - - - - BraintreeLoggerForTransactionSale - - - - - BraintreeLoggerForTransactionSale - - - - - BraintreeLoggerForTransactionSale - - - - - BraintreeLoggerForTransactionSale - - - - - + + - BraintreeSaleRequest + BraintreeVaultCaptureRequest + Magento\Braintree\Gateway\Http\TransferFactory + Magento\Braintree\Gateway\Http\Client\TransactionSale + Magento\Braintree\Gateway\Response\TransactionIdHandler + Magento\Braintree\Gateway\Validator\ResponseValidator - + - BraintreeAuthorizeRequest + Magento\Braintree\Gateway\Request\VaultCaptureDataBuilder Magento\Braintree\Gateway\Request\SettlementDataBuilder - - + + + + - BraintreeVaultSaleRequest + BraintreePayPalAuthorizeRequest + BraintreePayPalResponseHandler - + - BraintreeVaultAuthorizeRequest - Magento\Braintree\Gateway\Request\SettlementDataBuilder + Magento\Braintree\Gateway\Request\CustomerDataBuilder + Magento\Braintree\Gateway\Request\PaymentDataBuilder + Magento\Braintree\Gateway\Request\ChannelDataBuilder + Magento\Braintree\Gateway\Request\PayPal\VaultDataBuilder + Magento\Braintree\Gateway\Request\PayPal\DeviceDataBuilder + Magento\Braintree\Gateway\Request\DescriptorDataBuilder @@ -254,45 +332,46 @@ - - - + + - BraintreeCaptureRequest - Magento\Braintree\Gateway\Http\TransferFactory - Magento\Braintree\Gateway\Http\Client\TransactionSubmitForSettlement - Magento\Braintree\Gateway\Response\TransactionIdHandler - Magento\Braintree\Gateway\Validator\ResponseValidator + BraintreePayPalVaultAuthorizeRequest + BraintreePayPalVaultResponseHandler - + - Magento\Braintree\Gateway\Request\CaptureDataBuilder + Magento\Braintree\Gateway\Request\CustomerDataBuilder + Magento\Braintree\Gateway\Request\PaymentDataBuilder + Magento\Braintree\Gateway\Request\ChannelDataBuilder + Magento\Braintree\Gateway\Request\AddressDataBuilder + Magento\Braintree\Gateway\Request\DescriptorDataBuilder - - - + + - BraintreeVaultCaptureRequest - Magento\Braintree\Gateway\Http\TransferFactory - Magento\Braintree\Gateway\Http\Client\TransactionSale - Magento\Braintree\Gateway\Response\TransactionIdHandler - Magento\Braintree\Gateway\Validator\ResponseValidator + BraintreePayPalVaultSaleRequest - + - Magento\Braintree\Gateway\Request\VaultCaptureDataBuilder + BraintreePayPalVaultAuthorizeRequest Magento\Braintree\Gateway\Request\SettlementDataBuilder - + + + + + Magento\Vault\Model\CreditCardTokenFactory + + @@ -330,17 +409,14 @@ - - - - Magento\Braintree\Gateway\Response\PaymentDetailsHandler - Magento\Braintree\Gateway\Response\TransactionIdHandler - Magento\Braintree\Gateway\Response\PayPalDetailsHandler - - - + + + + Magento\Vault\Model\AccountPaymentTokenFactory + + @@ -356,7 +432,27 @@ Magento\Braintree\Gateway\Config\PayPal\Config - + + + + Magento\Braintree\Gateway\Response\PaymentDetailsHandler + Magento\Braintree\Gateway\Response\TransactionIdHandler + Magento\Braintree\Gateway\Response\PayPalDetailsHandler + Magento\Braintree\Gateway\Response\PayPal\VaultDetailsHandler + + + + + + + Magento\Braintree\Gateway\Response\PaymentDetailsHandler + Magento\Braintree\Gateway\Response\TransactionIdHandler + Magento\Braintree\Gateway\Response\PayPalDetailsHandler + + + + + @@ -379,7 +475,7 @@ - + Magento\Braintree\Gateway\Config\Config @@ -392,6 +488,22 @@ + + + + + + Magento\Braintree\Gateway\Config\PayPal\Config + + + + + + BraintreePayPalCountryValidator + + + + @@ -404,6 +516,7 @@ + @@ -411,19 +524,16 @@ - BraintreeTransactionsCollectionFactoryForReporting - BraintreeTransactionsReporting - @@ -433,5 +543,17 @@ - + + + + + 1 + 1 + 1 + 1 + 1 + 1 + + + diff --git a/app/code/Magento/Braintree/etc/events.xml b/app/code/Magento/Braintree/etc/events.xml index 6d76a626d15bd..2bf95bdbad178 100644 --- a/app/code/Magento/Braintree/etc/events.xml +++ b/app/code/Magento/Braintree/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/etc/frontend/di.xml b/app/code/Magento/Braintree/etc/frontend/di.xml index 98ae47dea794a..781f985b4b3a8 100644 --- a/app/code/Magento/Braintree/etc/frontend/di.xml +++ b/app/code/Magento/Braintree/etc/frontend/di.xml @@ -1,7 +1,7 @@ @@ -10,6 +10,7 @@ Magento\Braintree\Model\Ui\ConfigProvider + Magento\Braintree\Model\Ui\PayPal\ConfigProvider @@ -32,6 +33,7 @@ Magento\Braintree\Model\Ui\TokenUiComponentProvider + Magento\Braintree\Model\Ui\PayPal\TokenUiComponentProvider diff --git a/app/code/Magento/Braintree/etc/frontend/events.xml b/app/code/Magento/Braintree/etc/frontend/events.xml index df1db1420b5a1..e1bff1a20b238 100644 --- a/app/code/Magento/Braintree/etc/frontend/events.xml +++ b/app/code/Magento/Braintree/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/etc/frontend/routes.xml b/app/code/Magento/Braintree/etc/frontend/routes.xml index 7ec5a0c1b097c..ad8b484ca30d6 100644 --- a/app/code/Magento/Braintree/etc/frontend/routes.xml +++ b/app/code/Magento/Braintree/etc/frontend/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/etc/frontend/sections.xml b/app/code/Magento/Braintree/etc/frontend/sections.xml index f87695a624730..add86f4cdb5cc 100644 --- a/app/code/Magento/Braintree/etc/frontend/sections.xml +++ b/app/code/Magento/Braintree/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/etc/module.xml b/app/code/Magento/Braintree/etc/module.xml index 2b7759fc7843b..56f0fa6108783 100644 --- a/app/code/Magento/Braintree/etc/module.xml +++ b/app/code/Magento/Braintree/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/i18n/en_US.csv b/app/code/Magento/Braintree/i18n/en_US.csv index f912e59c2edac..f5e2d36e1e9bb 100644 --- a/app/code/Magento/Braintree/i18n/en_US.csv +++ b/app/code/Magento/Braintree/i18n/en_US.csv @@ -140,6 +140,29 @@ Debug,Debug "liabilityShifted", "Liability Shifted" "liabilityShiftPossible", "Liability Shift Possible" "riskDataId", "Risk ID" -"riskDataDecision", "Risk Decision", -"paymentId", "Payment Id", -"payerEmail", "Payer Email", +"riskDataDecision", "Risk Decision" +"paymentId", "Payment Id" +"payerEmail", "Payer Email" +"sale","Sale" +"credit","Credit" +"authorization_expired","Authorization expired" +"authorizing","Authorizing" +"authorized","Authorized" +"gateway_rejected","Gateway rejected" +"failed","Failed" +"processor_declined","Processor declined" +"settled","Settled" +"settling","Settling" +"submitted_for_settlement","Submitted for settlement" +"voided","Voided" +"unrecognized","Unrecognized" +"settlement_declined","Settlement declined" +"settlement_pending","Settlement pending" +"settlement_confirmed","Settlement confirmed" +"paypal_account","Paypal account" +"coinbase_account","Coinbase account" +"europe_bank_accout","Europe bank account" +"credit_card","Credit card" +"apple_pay_card","Apple pay card" +"android_pay_card","Android pay card" +"Accept credit/debit cards and PayPal in your Magento store.
No setup or monthly fees and your customers never leave your store to complete the purchase.","Accept credit/debit cards and PayPal in your Magento store.
No setup or monthly fees and your customers never leave your store to complete the purchase." \ No newline at end of file diff --git a/app/code/Magento/Braintree/registration.php b/app/code/Magento/Braintree/registration.php index 33f9f68a4197b..d56ac32c07c96 100644 --- a/app/code/Magento/Braintree/registration.php +++ b/app/code/Magento/Braintree/registration.php @@ -1,6 +1,6 @@ @@ -9,4 +9,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Braintree/view/adminhtml/layout/braintree_report_index.xml b/app/code/Magento/Braintree/view/adminhtml/layout/braintree_report_index.xml index 30c334cd09464..396f86b903fd5 100644 --- a/app/code/Magento/Braintree/view/adminhtml/layout/braintree_report_index.xml +++ b/app/code/Magento/Braintree/view/adminhtml/layout/braintree_report_index.xml @@ -1,7 +1,7 @@ @@ -18,4 +18,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml index 76f6b5a4d616c..b5ce1fc9c6792 100644 --- a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml +++ b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml @@ -1,7 +1,7 @@ @@ -18,13 +18,17 @@ braintree_cc_vault Magento_Vault::form/vault.phtml + + braintree_paypal_vault + Magento_Vault::form/vault.phtml + + class="Magento\Braintree\Block\Payment" + after="billing_method"/> diff --git a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml index 68e0abc0cd009..0cfa34cf020c1 100644 --- a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml +++ b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml @@ -1,7 +1,7 @@ @@ -18,6 +18,10 @@ braintree_cc_vault Magento_Vault::form/vault.phtml + + braintree_paypal_vault + Magento_Vault::form/vault.phtml + - \ No newline at end of file + diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml index cd2fbcf3fec7a..50076da1a851f 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml @@ -1,6 +1,6 @@ getData(TokenUiComponentProviderInterface::COMPONENT_DETAILS); +$icon = $details['icon']; +$id = $block->escapeHtml($block->getData('id')); +?> +
", + "nonceUrl": "escapeUrl($block->getData('nonceUrl')); ?>" + } + }' id="payment_" class="admin__field"> +
+ + + escapeHtml($details['payerEmail']); ?> +
+
diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml index 3811461884725..5414be0a571e9 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml @@ -1,13 +1,13 @@ getData('details'); +$details = $block->getData(TokenUiComponentProviderInterface::COMPONENT_DETAILS); $icon = $block->getData('icons')[$details['type']]; $id = $block->escapeHtml($block->getData('id')); ?> @@ -15,6 +15,7 @@ $id = $block->escapeHtml($block->getData('id')); "Magento_Braintree/js/vault": { "container": "payment_", "publicHash": "escapeHtml($block->getData(TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH)); ?>", + "code": "escapeHtml($block->getData('code')); ?>", "nonceUrl": "escapeUrl($block->getData('nonceUrl')); ?>" } }' id="payment_" class="admin__field"> diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/grid/tooltip.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/grid/tooltip.phtml index 7a07fe648f315..34c109e2d69f8 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/grid/tooltip.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/grid/tooltip.phtml @@ -1,6 +1,6 @@ escapeHtml($block->getCode()); payment = new Braintree(config); }); //]]> - \ No newline at end of file + diff --git a/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml b/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml index d1b661b2c3ecd..2772c5328f100 100644 --- a/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml +++ b/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ braintree_report.braintree_report_data_source braintree_report_columns + Magento_Braintree::settlement_report @@ -109,7 +110,6 @@ - @@ -135,6 +134,22 @@ + + + + ${ $.parentName } + + componentType = column, index = ${ $.index }:visible + + braintree_report.braintree_report.listing_top.listing_filters + ui/grid/filters/elements/group + Magento_Ui/js/grid/filters/range + date + createdAt + Created At + + + @@ -216,7 +231,6 @@ desc - dateRange date Magento_Ui/js/grid/columns/date Created At diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js b/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js index 93b2f9831ef35..2457e3582a15e 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js +++ b/app/code/Magento/Braintree/view/adminhtml/web/js/braintree.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/grid/filters/status.html b/app/code/Magento/Braintree/view/adminhtml/web/js/grid/filters/status.html index 68c1dbcee8f45..f69cbcc619846 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/js/grid/filters/status.html +++ b/app/code/Magento/Braintree/view/adminhtml/web/js/grid/filters/status.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/grid/provider.js b/app/code/Magento/Braintree/view/adminhtml/web/js/grid/provider.js index ff0f8408b4079..8b1380f6029be 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/js/grid/provider.js +++ b/app/code/Magento/Braintree/view/adminhtml/web/js/grid/provider.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js index fcff173e7fcd4..47decbb18bdbe 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js +++ b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ @@ -14,7 +14,8 @@ define([ return Class.extend({ defaults: { $selector: null, - selector: 'edit_form' + selector: 'edit_form', + $container: null }, /** @@ -25,17 +26,18 @@ define([ var self = this; self.$selector = $('#' + self.selector); + self.$container = $('#' + self.container); self.$selector.on( - 'setVaultNotActive', + 'setVaultNotActive.' + self.getCode(), function () { - self.$selector.off('submitOrder.braintree_vault'); + self.$selector.off('submitOrder.' + self.getCode()); } ); - this._super(); + self._super(); - this.initEventHandlers(); + self.initEventHandlers(); - return this; + return self; }, /** @@ -43,14 +45,14 @@ define([ * @returns {String} */ getCode: function () { - return 'braintree'; + return this.code; }, /** * Init event handlers */ initEventHandlers: function () { - $('#' + this.container).find('[name="payment[token_switcher]"]') + $(this.$container).find('[name="payment[token_switcher]"]') .on('click', this.selectPaymentMethod.bind(this)); }, @@ -66,7 +68,7 @@ define([ * Enable form event listeners */ enableEventListeners: function () { - this.$selector.on('submitOrder.braintree_vault', this.submitOrder.bind(this)); + this.$selector.on('submitOrder.' + this.getCode(), this.submitOrder.bind(this)); }, /** @@ -107,7 +109,7 @@ define([ $('body').trigger('processStart'); - $.get(self.nonceUrl, { + $.getJSON(self.nonceUrl, { 'public_hash': self.publicHash }).done(function (response) { self.setPaymentDetails(response.paymentMethodNonce); @@ -129,7 +131,7 @@ define([ this.createPublicHashSelector(); this.$selector.find('[name="payment[public_hash]"]').val(this.publicHash); - this.$selector.find('#braintree_nonce').val(nonce); + this.$container.find('#' + this.getNonceSelectorName()).val(nonce); }, /** @@ -138,16 +140,16 @@ define([ createPublicHashSelector: function () { var $input; - if (this.$selector.find('#braintree_nonce').size() === 0) { + if (this.$container.find('#' + this.getNonceSelectorName()).size() === 0) { $input = $('').attr( { type: 'hidden', - id: 'braintree_nonce', + id: this.getNonceSelectorName(), name: 'payment[payment_method_nonce]' } ); - $input.appendTo(this.$selector); + $input.appendTo(this.$container); $input.prop('disabled', false); } }, @@ -160,6 +162,14 @@ define([ alert({ content: message }); + }, + + /** + * Get selector name for nonce input + * @returns {String} + */ + getNonceSelectorName: function () { + return 'nonce_' + this.getCode(); } }); }); diff --git a/app/code/Magento/Braintree/view/adminhtml/web/styles.css b/app/code/Magento/Braintree/view/adminhtml/web/styles.css index c0d8822e779d4..19a4f794fb428 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/styles.css +++ b/app/code/Magento/Braintree/view/adminhtml/web/styles.css @@ -1,7 +1,8 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -.braintree-section .entry-edit-head > .config-heading .heading strong {padding-left:150px;background:url(images/braintree_logo.png) no-repeat 0 0 / 145px auto;line-height:36px;} -.braintree-section .entry-edit-head > .config-heading:before {background: url("images/braintree_allinone.png") no-repeat 0 0 / 100% auto;content: "";display: inline;float: right;height: 35px;width: 280px;} +.braintree-section .heading {background: url("images/braintree_logo.png") no-repeat 0 50% / 18rem auto; padding-left: 20rem;} +.braintree-section .button-container {float: right;} +.braintree-section .config-alt {background: url("images/braintree_allinone.png") no-repeat scroll 0 0 / 100% auto; height: 28px; margin: 0.5rem 0 0; width: 230px;} diff --git a/app/code/Magento/Braintree/view/base/web/images/paypal-small.png b/app/code/Magento/Braintree/view/base/web/images/paypal-small.png new file mode 100644 index 0000000000000..92d5c63bca442 Binary files /dev/null and b/app/code/Magento/Braintree/view/base/web/images/paypal-small.png differ diff --git a/app/code/Magento/Braintree/view/base/web/images/paypal.png b/app/code/Magento/Braintree/view/base/web/images/paypal.png new file mode 100644 index 0000000000000..291693037814a Binary files /dev/null and b/app/code/Magento/Braintree/view/base/web/images/paypal.png differ diff --git a/app/code/Magento/Braintree/view/base/web/js/validator.js b/app/code/Magento/Braintree/view/base/web/js/validator.js index 8c878840ca10c..931774aaffa2d 100644 --- a/app/code/Magento/Braintree/view/base/web/js/validator.js +++ b/app/code/Magento/Braintree/view/base/web/js/validator.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ diff --git a/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml b/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml index 19b7a795c2dc2..a5125861a048f 100644 --- a/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml +++ b/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Braintree/view/frontend/layout/checkout_index_index.xml index a6b5b8795c46b..872cb7d51ce1f 100644 --- a/app/code/Magento/Braintree/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Braintree/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Braintree/view/frontend/layout/vault_cards_listaction.xml b/app/code/Magento/Braintree/view/frontend/layout/vault_cards_listaction.xml index b7bf5919a7e15..1ab68abf1976d 100644 --- a/app/code/Magento/Braintree/view/frontend/layout/vault_cards_listaction.xml +++ b/app/code/Magento/Braintree/view/frontend/layout/vault_cards_listaction.xml @@ -1,7 +1,7 @@ @@ -11,6 +11,9 @@ + + + diff --git a/app/code/Magento/Braintree/view/frontend/requirejs-config.js b/app/code/Magento/Braintree/view/frontend/requirejs-config.js index c08a45bdbecd7..e12a4dd87043e 100644 --- a/app/code/Magento/Braintree/view/frontend/requirejs-config.js +++ b/app/code/Magento/Braintree/view/frontend/requirejs-config.js @@ -1,12 +1,12 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ var config = { map: { '*': { - braintree: 'https://js.braintreegateway.com/js/braintree-2.17.6.min.js' + braintree: 'https://js.braintreegateway.com/js/braintree-2.25.0.min.js' } } }; diff --git a/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml b/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml index 35cb4617ec9ed..5fc4bf83cab28 100644 --- a/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml +++ b/app/code/Magento/Braintree/view/frontend/templates/paypal/button.phtml @@ -1,6 +1,6 @@ escapeHtml($block->getPayerEmail()); +?> + + + <?php echo $block->escapeHtml(__('PayPal Logo')); ?> + + + +
+ getBlockHtml('formkey'); ?> + + +
+ + diff --git a/app/code/Magento/Braintree/view/frontend/web/js/paypal/button.js b/app/code/Magento/Braintree/view/frontend/web/js/paypal/button.js index c2a5326aa31f6..0050a50a97d55 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/paypal/button.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/paypal/button.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define( diff --git a/app/code/Magento/Braintree/view/frontend/web/js/paypal/form-builder.js b/app/code/Magento/Braintree/view/frontend/web/js/paypal/form-builder.js index 0b199d3b479a5..66bee74960112 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/paypal/form-builder.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/paypal/form-builder.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define( diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js index 83a8ee5a453ea..d369fc93e1570 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/adapter.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/adapter.js index 7d34055512cf1..51f0b3f79ea64 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/adapter.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/adapter.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ @@ -76,6 +76,11 @@ define([ globalMessageList.addErrorMessage({ message: errorMessage }); - } + }, + + /** + * May be triggered on Braintree SDK setup + */ + onReady: function () {} }; }); diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/braintree.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/braintree.js index cb0b46a25327e..93cdb364ba121 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/braintree.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/braintree.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ @@ -7,26 +7,19 @@ define( [ 'uiComponent', - 'uiRegistry', - 'Magento_Braintree/js/view/payment/adapter', 'Magento_Checkout/js/model/payment/renderer-list' ], function ( Component, - Registry, - Braintree, rendererList ) { 'use strict'; var config = window.checkoutConfig.payment, braintreeType = 'braintree', - payPalType = 'braintree_paypal', - path = 'checkout.steps.billing-step.payment.payments-list.', - components = []; + payPalType = 'braintree_paypal'; if (config[braintreeType].isActive) { - components.push(path + braintreeType); rendererList.push( { type: braintreeType, @@ -44,13 +37,6 @@ define( ); } - // setup Braintree SDK with merged configuration from all related components - if (components.length) { - Registry.get(components, function () { - Braintree.setup(); - }); - } - /** Add view logic here if needed */ return Component.extend({}); } diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js index 6990c1e2e5a0b..f37aea1b48315 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ @@ -61,11 +61,23 @@ define( this.beforePlaceOrder(response); }, + /** + * Device data initialization + * + * @param {Object} checkout + */ + onReady: function (checkout) { + braintree.checkout = checkout; + braintree.onReady(); + }, + /** * Triggers on any Braintree error + * @param {Object} response */ - onError: function () { - this.paymentMethodNonce = null; + onError: function (response) { + braintree.showError($t('Payment ' + this.getTitle() + ' can\'t be initialized')); + throw response.message; }, /** @@ -90,7 +102,7 @@ define( this._super() .observe(['active']); this.validatorManager.initialize(); - this.initBraintree(); + this.initClientConfig(); return this; }, @@ -122,11 +134,11 @@ define( * @param {Boolean} isActive */ onActiveChange: function (isActive) { - if (!isActive || this.isSingleUse()) { + if (!isActive) { return; } - this.reInitBraintree(); + this.initBraintree(); }, /** @@ -146,17 +158,9 @@ define( }, /** - * Create Braintree configuration + * Init Braintree configuration */ initBraintree: function () { - this.initClientConfig(); - braintree.config = _.extend(braintree.config, this.clientConfig); - }, - - /** - * Re-init Braintree configuration - */ - reInitBraintree: function () { var intervalId = setInterval(function () { // stop loader when frame will be loaded if ($('#braintree-hosted-field-number').length) { @@ -165,6 +169,12 @@ define( } }, 500); + if (braintree.checkout) { + braintree.checkout.teardown(function () { + braintree.checkout = null; + }); + } + fullScreenLoader.startLoader(); braintree.setConfig(this.clientConfig); braintree.setup(); @@ -189,6 +199,7 @@ define( onReady: function (checkout) { braintree.checkout = checkout; this.additionalData['device_data'] = checkout.deviceData; + braintree.onReady(); } }; @@ -309,14 +320,6 @@ define( }); return false; - }, - - /** - * Check if Braintree configured without PayPal - * @returns {Boolean} - */ - isSingleUse: function () { - return window.checkoutConfig.payment[this.getCode()].isSingleUse; } }); } diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js index ef57428acaa3c..c7ca993d1cae3 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal-vault.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal-vault.js new file mode 100644 index 0000000000000..e51bc0f5ff5e6 --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal-vault.js @@ -0,0 +1,87 @@ +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define([ + 'jquery', + 'underscore', + 'Magento_Vault/js/view/payment/method-renderer/vault', + 'Magento_Ui/js/model/messageList', + 'Magento_Checkout/js/model/full-screen-loader' +], function ($, _, VaultComponent, globalMessageList, fullScreenLoader) { + 'use strict'; + + return VaultComponent.extend({ + defaults: { + template: 'Magento_Braintree/payment/paypal/vault', + additionalData: {} + }, + + /** + * Get PayPal payer email + * @returns {String} + */ + getPayerEmail: function () { + return this.details.payerEmail; + }, + + /** + * Get type of payment + * @returns {String} + */ + getPaymentIcon: function () { + return window.checkoutConfig.payment['braintree_paypal'].paymentIcon; + }, + + /** + * Place order + */ + beforePlaceOrder: function () { + this.getPaymentMethodNonce(); + }, + + /** + * Send request to get payment method nonce + */ + getPaymentMethodNonce: function () { + var self = this; + + fullScreenLoader.startLoader(); + $.getJSON(self.nonceUrl, { + 'public_hash': self.publicHash + }) + .done(function (response) { + fullScreenLoader.stopLoader(); + self.additionalData['payment_method_nonce'] = response.paymentMethodNonce; + self.placeOrder(); + }) + .fail(function (response) { + var error = JSON.parse(response.responseText); + + fullScreenLoader.stopLoader(); + globalMessageList.addErrorMessage({ + message: error.message + }); + }); + }, + + /** + * Get payment method data + * @returns {Object} + */ + getData: function () { + var data = { + 'method': this.code, + 'additional_data': { + 'public_hash': this.publicHash + } + }; + + data['additional_data'] = _.extend(data['additional_data'], this.additionalData); + + return data; + } + }); +}); diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js index df3d5a116699c..2c6efeaa105a4 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ @@ -11,8 +11,20 @@ define([ 'Magento_Braintree/js/view/payment/adapter', 'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/full-screen-loader', - 'Magento_Checkout/js/model/payment/additional-validators' -], function ($, _, Component, Braintree, quote, fullScreenLoader, additionalValidators) { + 'Magento_Checkout/js/model/payment/additional-validators', + 'Magento_Vault/js/view/payment/vault-enabler', + 'Magento_Checkout/js/action/create-billing-address' +], function ( + $, + _, + Component, + Braintree, + quote, + fullScreenLoader, + additionalValidators, + VaultEnabler, + createBillingAddress +) { 'use strict'; return Component.extend({ @@ -22,12 +34,24 @@ define([ active: false, paymentMethodNonce: null, grandTotalAmount: null, + isReviewRequired: false, + customerEmail: null, + + /** + * Additional payment data + * + * {Object} + */ + additionalData: {}, /** * PayPal client configuration * {Object} */ clientConfig: { + dataCollector: { + paypal: true + }, /** * Triggers when widget is loaded @@ -35,7 +59,9 @@ define([ */ onReady: function (checkout) { Braintree.checkout = checkout; + this.additionalData['device_data'] = checkout.deviceData; this.enableButton(); + Braintree.onReady(); }, /** @@ -59,17 +85,24 @@ define([ var self = this; this._super() - .observe(['active']); + .observe(['active', 'isReviewRequired', 'customerEmail']); + + this.vaultEnabler = new VaultEnabler(); + this.vaultEnabler.setPaymentCode(this.getVaultCode()); + this.vaultEnabler.isActivePaymentTokenEnabler.subscribe(function () { + self.onVaultPaymentTokenEnablerChange(); + }); this.grandTotalAmount = quote.totals()['base_grand_total']; quote.totals.subscribe(function () { if (self.grandTotalAmount !== quote.totals()['base_grand_total']) { self.grandTotalAmount = quote.totals()['base_grand_total']; - self.reInitPayPal(); } }); + // for each component initialization need update property + this.isReviewRequired(false); this.initClientConfig(); return this; @@ -130,8 +163,6 @@ define([ this.clientConfig[name] = fn.bind(this); } }, this); - - Braintree.config = _.extend(Braintree.config, this.clientConfig); }, /** @@ -151,14 +182,16 @@ define([ var billingAddress = { street: [address.streetAddress], city: address.locality, - regionCode: address.region, postcode: address.postalCode, countryId: address.countryCodeAlpha2, + email: customer.email, firstname: customer.firstName, lastname: customer.lastName, telephone: customer.phone }; + billingAddress['region_code'] = address.region; + billingAddress = createBillingAddress(billingAddress); quote.billingAddress(billingAddress); }, @@ -172,7 +205,13 @@ define([ if (quote.billingAddress() === null && typeof data.details.billingAddress !== 'undefined') { this.setBillingAddress(data.details, data.details.billingAddress); } - this.placeOrder(); + + if (this.isSkipOrderReview()) { + this.placeOrder(); + } else { + this.customerEmail(data.details.email); + this.isReviewRequired(true); + } }, /** @@ -192,15 +231,6 @@ define([ Braintree.setup(); }, - /** - * Triggers when customer click "Continue to PayPal" button - */ - payWithPayPal: function () { - if (additionalValidators.validate()) { - Braintree.checkout.paypal.initAuthFlow(); - } - }, - /** * Get locale * @returns {String} @@ -223,11 +253,12 @@ define([ */ getPayPalConfig: function () { var totals = quote.totals(), - config = {}; + config = {}, + isActiveVaultEnabler = this.isActiveVault(); config.paypal = { container: 'paypal-container', - singleUse: true, + singleUse: !isActiveVaultEnabler, headless: true, amount: this.grandTotalAmount, currency: totals['base_currency_code'], @@ -295,12 +326,18 @@ define([ * @returns {Object} */ getData: function () { - return { + var data = { 'method': this.getCode(), 'additional_data': { 'payment_method_nonce': this.paymentMethodNonce } }; + + data['additional_data'] = _.extend(data['additional_data'], this.additionalData); + + this.vaultEnabler.visitAdditionalData(data); + + return data; }, /** @@ -312,12 +349,43 @@ define([ return window.checkoutConfig.payment[this.getCode()].paymentAcceptanceMarkSrc; }, + /** + * @returns {String} + */ + getVaultCode: function () { + return window.checkoutConfig.payment[this.getCode()].vaultCode; + }, + + /** + * Check if need to skip order review + * @returns {Boolean} + */ + isSkipOrderReview: function () { + return window.checkoutConfig.payment[this.getCode()].skipOrderReview; + }, + + /** + * Checks if vault is active + * @returns {Boolean} + */ + isActiveVault: function () { + return this.vaultEnabler.isVaultEnabled() && this.vaultEnabler.isActivePaymentTokenEnabler(); + }, + + /** + * Re-init PayPal Auth flow to use Vault + */ + onVaultPaymentTokenEnablerChange: function () { + this.clientConfig.paypal.singleUse = !this.isActiveVault(); + this.reInitPayPal(); + }, + /** * Disable submit button */ disableButton: function () { // stop any previous shown loaders - fullScreenLoader.stopLoader(); + fullScreenLoader.stopLoader(true); fullScreenLoader.startLoader(); $('[data-button="place"]').attr('disabled', 'disabled'); }, @@ -328,6 +396,31 @@ define([ enableButton: function () { $('[data-button="place"]').removeAttr('disabled'); fullScreenLoader.stopLoader(); + }, + + /** + * Triggers when customer click "Continue to PayPal" button + */ + payWithPayPal: function () { + if (additionalValidators.validate()) { + Braintree.checkout.paypal.initAuthFlow(); + } + }, + + /** + * Get button title + * @returns {String} + */ + getButtonTitle: function () { + return this.isSkipOrderReview() ? 'Pay with PayPal' : 'Continue to PayPal'; + }, + + /** + * Get button id + * @returns {String} + */ + getButtonId: function () { + return this.getCode() + (this.isSkipOrderReview() ? '_pay_with' : '_continue_to'); } }); }); diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js index b1b13e9c13ac0..a89c0c9877d09 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js @@ -1,16 +1,16 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ /*global define*/ define([ 'jquery', - 'Magento_Braintree/js/view/payment/method-renderer/cc-form', 'Magento_Vault/js/view/payment/method-renderer/vault', + 'Magento_Braintree/js/view/payment/adapter', 'Magento_Ui/js/model/messageList', 'Magento_Checkout/js/model/full-screen-loader' -], function ($, Component, VaultComponent, globalMessageList, fullScreenLoader) { +], function ($, VaultComponent, Braintree, globalMessageList, fullScreenLoader) { 'use strict'; return VaultComponent.extend({ @@ -49,7 +49,17 @@ define([ * Place order */ placeOrder: function () { - this.getPaymentMethodNonce(); + var self = this; + + /** + * Define already callback + */ + Braintree.onReady = function () { + self.getPaymentMethodNonce(); + }; + self.hostedFields(function (formComponent) { + formComponent.initBraintree(); + }); }, /** @@ -59,7 +69,7 @@ define([ var self = this; fullScreenLoader.startLoader(); - $.get(self.nonceUrl, { + $.getJSON(self.nonceUrl, { 'public_hash': self.publicHash }) .done(function (response) { diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/validator-handler.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/validator-handler.js index d253b8e5625dd..57b8d96abc16d 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/validator-handler.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/validator-handler.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ diff --git a/app/code/Magento/Braintree/view/frontend/web/template/payment/form.html b/app/code/Magento/Braintree/view/frontend/web/template/payment/form.html index 9d1dda23c2d84..888f800581d46 100644 --- a/app/code/Magento/Braintree/view/frontend/web/template/payment/form.html +++ b/app/code/Magento/Braintree/view/frontend/web/template/payment/form.html @@ -1,15 +1,15 @@
+ name="payment[method]" + class="radio" + data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/> @@ -109,8 +109,8 @@ -
- \ No newline at end of file + diff --git a/app/code/Magento/Braintree/view/frontend/web/template/payment/paypal.html b/app/code/Magento/Braintree/view/frontend/web/template/payment/paypal.html index f392d21b04091..8df52975917b9 100644 --- a/app/code/Magento/Braintree/view/frontend/web/template/payment/paypal.html +++ b/app/code/Magento/Braintree/view/frontend/web/template/payment/paypal.html @@ -1,6 +1,6 @@ @@ -21,22 +21,59 @@
-
+
-
+ +
+ + +
+ + + +
+
+
+ +
+ +
+ +
+
+
-
\ No newline at end of file + diff --git a/app/code/Magento/Braintree/view/frontend/web/template/payment/paypal/vault.html b/app/code/Magento/Braintree/view/frontend/web/template/payment/paypal/vault.html new file mode 100644 index 0000000000000..28cd3ebb2f2d1 --- /dev/null +++ b/app/code/Magento/Braintree/view/frontend/web/template/payment/paypal/vault.html @@ -0,0 +1,47 @@ + +
+
+ + +
+ +
+ +
+ + + +
+
+
+ +
+
+
+
diff --git a/app/code/Magento/Bundle/Api/Data/BundleOptionInterface.php b/app/code/Magento/Bundle/Api/Data/BundleOptionInterface.php index a10d131c000ce..5ef6c2971b18b 100644 --- a/app/code/Magento/Bundle/Api/Data/BundleOptionInterface.php +++ b/app/code/Magento/Bundle/Api/Data/BundleOptionInterface.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Bundle/etc/adminhtml/events.xml b/app/code/Magento/Bundle/etc/adminhtml/events.xml index 3e1de66c1fdd3..cd8af005694ea 100644 --- a/app/code/Magento/Bundle/etc/adminhtml/events.xml +++ b/app/code/Magento/Bundle/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/adminhtml/routes.xml b/app/code/Magento/Bundle/etc/adminhtml/routes.xml index e140d1b6875a4..d2e7c9c3b20f9 100644 --- a/app/code/Magento/Bundle/etc/adminhtml/routes.xml +++ b/app/code/Magento/Bundle/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/catalog_attributes.xml b/app/code/Magento/Bundle/etc/catalog_attributes.xml index 832ba71237c0b..8c45aaab6c46f 100644 --- a/app/code/Magento/Bundle/etc/catalog_attributes.xml +++ b/app/code/Magento/Bundle/etc/catalog_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/config.xml b/app/code/Magento/Bundle/etc/config.xml index abaed7a879f2b..0016210cd149d 100644 --- a/app/code/Magento/Bundle/etc/config.xml +++ b/app/code/Magento/Bundle/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/di.xml b/app/code/Magento/Bundle/etc/di.xml index 74e4e7d4d09e0..2899ce28d0400 100644 --- a/app/code/Magento/Bundle/etc/di.xml +++ b/app/code/Magento/Bundle/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/extension_attributes.xml b/app/code/Magento/Bundle/etc/extension_attributes.xml index 3819e892e6ff1..d23dfc71b39fc 100644 --- a/app/code/Magento/Bundle/etc/extension_attributes.xml +++ b/app/code/Magento/Bundle/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/frontend/di.xml b/app/code/Magento/Bundle/etc/frontend/di.xml index acaf67ac82e5e..084f681df7e03 100644 --- a/app/code/Magento/Bundle/etc/frontend/di.xml +++ b/app/code/Magento/Bundle/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/frontend/events.xml b/app/code/Magento/Bundle/etc/frontend/events.xml index ce21acda965de..d08cdb4bcc997 100644 --- a/app/code/Magento/Bundle/etc/frontend/events.xml +++ b/app/code/Magento/Bundle/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/module.xml b/app/code/Magento/Bundle/etc/module.xml index 982a33d00bc6b..77b78dcc43284 100644 --- a/app/code/Magento/Bundle/etc/module.xml +++ b/app/code/Magento/Bundle/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/pdf.xml b/app/code/Magento/Bundle/etc/pdf.xml index 085e7946cb7d6..912aa1426efa1 100644 --- a/app/code/Magento/Bundle/etc/pdf.xml +++ b/app/code/Magento/Bundle/etc/pdf.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/product_types.xml b/app/code/Magento/Bundle/etc/product_types.xml index c3f909afbeabe..6168189a3b4e3 100644 --- a/app/code/Magento/Bundle/etc/product_types.xml +++ b/app/code/Magento/Bundle/etc/product_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/sales.xml b/app/code/Magento/Bundle/etc/sales.xml index 74e5647051dec..3094eb6bfecfa 100644 --- a/app/code/Magento/Bundle/etc/sales.xml +++ b/app/code/Magento/Bundle/etc/sales.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/webapi.xml b/app/code/Magento/Bundle/etc/webapi.xml index 6e31986be7b8f..69124309687a3 100644 --- a/app/code/Magento/Bundle/etc/webapi.xml +++ b/app/code/Magento/Bundle/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/webapi_rest/di.xml b/app/code/Magento/Bundle/etc/webapi_rest/di.xml index acaf67ac82e5e..084f681df7e03 100644 --- a/app/code/Magento/Bundle/etc/webapi_rest/di.xml +++ b/app/code/Magento/Bundle/etc/webapi_rest/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/etc/webapi_soap/di.xml b/app/code/Magento/Bundle/etc/webapi_soap/di.xml index acaf67ac82e5e..084f681df7e03 100644 --- a/app/code/Magento/Bundle/etc/webapi_soap/di.xml +++ b/app/code/Magento/Bundle/etc/webapi_soap/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/registration.php b/app/code/Magento/Bundle/registration.php index 48ae2414286eb..53f3657ae0519 100644 --- a/app/code/Magento/Bundle/registration.php +++ b/app/code/Magento/Bundle/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/adminhtml_order_shipment_view.xml b/app/code/Magento/Bundle/view/adminhtml/layout/adminhtml_order_shipment_view.xml index 34975692a948b..6b97971a0ee51 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/adminhtml_order_shipment_view.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/adminhtml_order_shipment_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_bundle.xml b/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_bundle.xml index 14ab43a776bbb..d0fdb184355d7 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_bundle.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_bundle.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_new.xml b/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_new.xml index 251a2ddd68af6..a496ea7538923 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_new.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_view_type_bundle.xml b/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_view_type_bundle.xml index 370ef3cf8afca..15374cb987d36 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_view_type_bundle.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/catalog_product_view_type_bundle.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/customer_index_wishlist.xml b/app/code/Magento/Bundle/view/adminhtml/layout/customer_index_wishlist.xml index b7a0c9d03e16e..7e37070109921 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/customer_index_wishlist.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/customer_index_wishlist.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_new.xml b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_new.xml index f3962e20d4435..99fdab5a7e9f4 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_new.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml index f3962e20d4435..99fdab5a7e9f4 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_view.xml b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_view.xml index 5f2c852416e04..323aba1d186e6 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_view.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_creditmemo_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_new.xml b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_new.xml index 9b37d8286fdcb..b03ce7a9cb451 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_new.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_updateqty.xml b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_updateqty.xml index 9b37d8286fdcb..b03ce7a9cb451 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_updateqty.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_updateqty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_view.xml b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_view.xml index 752031796631f..34c3470cf06a7 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_view.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_invoice_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_view.xml b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_view.xml index 2c6a8fe93caa9..62f0305194fa9 100644 --- a/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_view.xml +++ b/app/code/Magento/Bundle/view/adminhtml/layout/sales_order_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/catalog/product/edit/tab/attributes/extend.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/catalog/product/edit/tab/attributes/extend.phtml index 0dff5ef370825..84e87afd48180 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/catalog/product/edit/tab/attributes/extend.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/catalog/product/edit/tab/attributes/extend.phtml @@ -1,6 +1,6 @@ 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 8fddd0798f7b4..41923c4826432 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 @@ -1,6 +1,6 @@ @@ -12,6 +12,7 @@ bundle_product_listing.bundle_product_listing_data_source
product_columns + Magento_Catalog::products
diff --git a/app/code/Magento/Bundle/view/adminhtml/web/css/bundle-product.css b/app/code/Magento/Bundle/view/adminhtml/web/css/bundle-product.css index 3503d6050e777..d5aed8a7d652e 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/css/bundle-product.css +++ b/app/code/Magento/Bundle/view/adminhtml/web/css/bundle-product.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-product.js b/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-product.js index a4e47177bdf22..53b08e43614a0 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-product.js +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-product.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-type-handler.js b/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-type-handler.js index 12dda7d3a148c..7f4a57cb530da 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-type-handler.js +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/bundle-type-handler.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true expr:true*/ diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-checkbox.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-checkbox.js index b7a05076ae268..9c2432bade43f 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-checkbox.js +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-checkbox.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js index 14dd426ed02aa..cee0489cc901a 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js index a52d4e8a4683b..7b5734c7451ea 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Bundle/view/base/layout/catalog_product_prices.xml b/app/code/Magento/Bundle/view/base/layout/catalog_product_prices.xml index 92d76cdfaa580..5f7d22ba2650b 100644 --- a/app/code/Magento/Bundle/view/base/layout/catalog_product_prices.xml +++ b/app/code/Magento/Bundle/view/base/layout/catalog_product_prices.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/base/templates/product/price/final_price.phtml b/app/code/Magento/Bundle/view/base/templates/product/price/final_price.phtml index 4c11b0ba1fe50..efd75677d3061 100644 --- a/app/code/Magento/Bundle/view/base/templates/product/price/final_price.phtml +++ b/app/code/Magento/Bundle/view/base/templates/product/price/final_price.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_simple.xml b/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_simple.xml index e31437ec63963..fedd29f952b02 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_simple.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_simple.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_configure_type_bundle.xml b/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_configure_type_bundle.xml index e7128e45ddc7b..adb1b2911983b 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_configure_type_bundle.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_configure_type_bundle.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_item_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_item_renderers.xml index c5d613183e640..9abf0a4018980 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_item_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/checkout_cart_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml index 09a27341fd5da..ddede2340995b 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/checkout_onepage_review_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/default.xml b/app/code/Magento/Bundle/view/frontend/layout/default.xml index a54d4b652b685..cb14616af5980 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/default.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 4db5f73f55bc5..991011db9fa08 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml index 1dba5769c0207..0e32c9fd9e816 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml index 6e1b90abf4d4e..927214fbcc174 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml index 7846245018a74..7463caa738083 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_email_order_shipment_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml index 7896e92bd34f4..c94b4957d267b 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml index 850e546a93a5a..d07959385bd9f 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml index 317b142514b9d..fb26de5bc2fdd 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml index dc5fb238dfd77..8c328c87a5c65 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml index 450f18d863ab5..57e39795df7da 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml index c4741ad6119f5..510168ac55e8a 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml index e3c91f1da5c20..f46b6260f3bd8 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_print_shipment_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml b/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml index ce42a5466cf06..536953423a3f2 100644 --- a/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml +++ b/app/code/Magento/Bundle/view/frontend/layout/sales_order_shipment_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Bundle/view/frontend/requirejs-config.js b/app/code/Magento/Bundle/view/frontend/requirejs-config.js index 9dd12524124a6..51ab4cab6bb2c 100644 --- a/app/code/Magento/Bundle/view/frontend/requirejs-config.js +++ b/app/code/Magento/Bundle/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -12,4 +12,4 @@ var config = { productSummary: 'Magento_Bundle/js/product-summary' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/backbutton.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/backbutton.phtml index ddb483cf0220d..86cd52b6dc6fd 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/backbutton.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/backbutton.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/customize.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/customize.phtml index e72be96db1ab0..e3538ebd6caea 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/customize.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/customize.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/summary.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/summary.phtml index cb1de4e05e8a4..0fc7e6f9c8f06 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/summary.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/summary.phtml @@ -1,6 +1,6 @@ parseAdditionalAttributes($dataRow['additional_attributes']); $dataRow['additional_attributes'] = $this->getNotBundleAttributes($additionalAttributes); } @@ -349,17 +346,37 @@ protected function cleanNotBundleAdditionalAttributes($dataRow) */ protected function getNotBundleAttributes($additionalAttributes) { - $cleanedAdditionalAttributes = ''; - foreach ($additionalAttributes as $attribute) { - list($attributeCode, $attributeValue) = explode(ImportProductModel::PAIR_NAME_VALUE_SEPARATOR, $attribute); - if (!in_array('bundle_' . $attributeCode, $this->getBundleColumns())) { - $cleanedAdditionalAttributes .= $attributeCode - . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR - . $attributeValue - . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; + $filteredAttributes = []; + foreach ($additionalAttributes as $code => $value) { + if (!in_array('bundle_' . $code, $this->getBundleColumns())) { + $filteredAttributes[] = $code . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $value; } } + return implode(ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $filteredAttributes); + } - return rtrim($cleanedAdditionalAttributes, ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR); + /** + * Retrieves additional attributes as array code=>value + * + * @param string $additionalAttributes + * @return array + */ + private function parseAdditionalAttributes($additionalAttributes) + { + $attributeNameValuePairs = explode(ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalAttributes); + $preparedAttributes = []; + $code = ''; + foreach ($attributeNameValuePairs as $attributeData) { + if (strpos($attributeData, ImportProductModel::PAIR_NAME_VALUE_SEPARATOR) === false) { + if (!$code) { + continue; + } + $preparedAttributes[$code] .= ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR . $attributeData; + continue; + } + list($code, $value) = explode(ImportProductModel::PAIR_NAME_VALUE_SEPARATOR, $attributeData, 2); + $preparedAttributes[$code] = $value; + } + return $preparedAttributes; } } diff --git a/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php index 2d0f1264b6b8a..205dee67f24c9 100644 --- a/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php +++ b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php @@ -3,7 +3,7 @@ /** * Import entity of bundle product type * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\BundleImportExport\Model\Import\Product\Type; diff --git a/app/code/Magento/BundleImportExport/Test/Unit/Model/Export/Product/RowCustomizerTest.php b/app/code/Magento/BundleImportExport/Test/Unit/Model/Export/Product/RowCustomizerTest.php index 13b80298d4e4f..34621320602c3 100644 --- a/app/code/Magento/BundleImportExport/Test/Unit/Model/Export/Product/RowCustomizerTest.php +++ b/app/code/Magento/BundleImportExport/Test/Unit/Model/Export/Product/RowCustomizerTest.php @@ -1,6 +1,6 @@ rowCustomizerMock->prepareData($this->productResourceCollection, [1]); - $attributes = 'attribute=1,sku_type=1,price_type=1,price_view=1,weight_type=1,values=values,shipment_type=1'; + $attributes = 'attribute=1,sku_type=1,attribute2="Text",price_type=1,price_view=1,weight_type=1,' + . 'values=values,shipment_type=1,attribute3=One,Two,Three'; $dataRow = [ 'sku' => 'sku1', 'additional_attributes' => $attributes @@ -186,7 +187,7 @@ public function testAddData() $preparedRow = $preparedData->addData($dataRow, 1); $expected = [ 'sku' => 'sku1', - 'additional_attributes' => 'attribute=1', + 'additional_attributes' => 'attribute=1,attribute2="Text",attribute3=One,Two,Three', 'bundle_price_type' => 'fixed', 'bundle_shipment_type' => 'separately', 'bundle_sku_type' => 'fixed', diff --git a/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php b/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php index 2379ad7f10701..fd25dc247c341 100644 --- a/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php +++ b/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/BundleImportExport/etc/export.xml b/app/code/Magento/BundleImportExport/etc/export.xml index 04312d79f0260..c7fd951bfab53 100644 --- a/app/code/Magento/BundleImportExport/etc/export.xml +++ b/app/code/Magento/BundleImportExport/etc/export.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/BundleImportExport/etc/import.xml b/app/code/Magento/BundleImportExport/etc/import.xml index 2c23489002b1f..8daa5296a8c39 100644 --- a/app/code/Magento/BundleImportExport/etc/import.xml +++ b/app/code/Magento/BundleImportExport/etc/import.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/BundleImportExport/etc/module.xml b/app/code/Magento/BundleImportExport/etc/module.xml index d042b3bc7eb79..64f2c06b3c770 100644 --- a/app/code/Magento/BundleImportExport/etc/module.xml +++ b/app/code/Magento/BundleImportExport/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/BundleImportExport/registration.php b/app/code/Magento/BundleImportExport/registration.php index b417e7d20b79e..b4f80e749f130 100644 --- a/app/code/Magento/BundleImportExport/registration.php +++ b/app/code/Magento/BundleImportExport/registration.php @@ -1,6 +1,6 @@ getEvent()->getObject(); + if (!is_object($object)) { + return; + } if ($this->config->getType() == \Magento\PageCache\Model\Config::VARNISH && $this->config->isEnabled()) { - $object = $observer->getEvent()->getObject(); - if ($object instanceof \Magento\Framework\DataObject\IdentityInterface) { - $tags = []; - $pattern = "((^|,)%s(,|$))"; - foreach ($object->getIdentities() as $tag) { - $tags[] = sprintf($pattern, $tag); - } - if (!empty($tags)) { - $this->purgeCache->sendPurgeRequest(implode('|', array_unique($tags))); - } + $bareTags = $this->getTagResolver()->getTags($object); + + $tags = []; + $pattern = "((^|,)%s(,|$))"; + foreach ($bareTags as $tag) { + $tags[] = sprintf($pattern, $tag); + } + if (!empty($tags)) { + $this->purgeCache->sendPurgeRequest(implode('|', array_unique($tags))); } + + } + } + + /** + * @deprecated + * @return \Magento\Framework\App\Cache\Tag\Resolver + */ + private function getTagResolver() + { + if ($this->tagResolver === null) { + $this->tagResolver = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\App\Cache\Tag\Resolver::class); } + return $this->tagResolver; } } diff --git a/app/code/Magento/CacheInvalidate/Test/Unit/Model/PurgeCacheTest.php b/app/code/Magento/CacheInvalidate/Test/Unit/Model/PurgeCacheTest.php index fede25d361481..637f2e14a8c57 100644 --- a/app/code/Magento/CacheInvalidate/Test/Unit/Model/PurgeCacheTest.php +++ b/app/code/Magento/CacheInvalidate/Test/Unit/Model/PurgeCacheTest.php @@ -1,6 +1,6 @@ configMock = $this->getMock( 'Magento\PageCache\Model\Config', ['getType', 'isEnabled'], @@ -39,6 +46,10 @@ protected function setUp() $this->configMock, $this->purgeCache ); + + $this->tagResolver = $this->getMock(\Magento\Framework\App\Cache\Tag\Resolver::class, [], [], '', false); + $helper->setBackwardCompatibleProperty($this->model, 'tagResolver', $this->tagResolver); + $this->observerMock = $this->getMock( 'Magento\Framework\Event\Observer', ['getEvent'], @@ -68,7 +79,7 @@ public function testInvalidateVarnish() $eventMock = $this->getMock('Magento\Framework\Event', ['getObject'], [], '', false); $eventMock->expects($this->once())->method('getObject')->will($this->returnValue($this->observerObject)); $this->observerMock->expects($this->once())->method('getEvent')->will($this->returnValue($eventMock)); - $this->observerObject->expects($this->once())->method('getIdentities')->will($this->returnValue($tags)); + $this->tagResolver->expects($this->once())->method('getTags')->will($this->returnValue($tags)); $this->purgeCache->expects($this->once())->method('sendPurgeRequest')->with($pattern); $this->model->execute($this->observerMock); diff --git a/app/code/Magento/CacheInvalidate/composer.json b/app/code/Magento/CacheInvalidate/composer.json index 8feceb694414d..01bbd0d8d97bd 100644 --- a/app/code/Magento/CacheInvalidate/composer.json +++ b/app/code/Magento/CacheInvalidate/composer.json @@ -2,12 +2,12 @@ "name": "magento/module-cache-invalidate", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/module-page-cache": "100.1.*", "magento/framework": "100.1.*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CacheInvalidate/etc/events.xml b/app/code/Magento/CacheInvalidate/etc/events.xml index 58ddeb64c9257..6103e661de55c 100644 --- a/app/code/Magento/CacheInvalidate/etc/events.xml +++ b/app/code/Magento/CacheInvalidate/etc/events.xml @@ -1,7 +1,7 @@ @@ -51,4 +51,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/CacheInvalidate/etc/module.xml b/app/code/Magento/CacheInvalidate/etc/module.xml index 7cc9d59df5959..b3277477fb62d 100644 --- a/app/code/Magento/CacheInvalidate/etc/module.xml +++ b/app/code/Magento/CacheInvalidate/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CacheInvalidate/registration.php b/app/code/Magento/CacheInvalidate/registration.php index 21f5baf8f333c..00ddee3f6776b 100644 --- a/app/code/Magento/CacheInvalidate/registration.php +++ b/app/code/Magento/CacheInvalidate/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Captcha/etc/adminhtml/events.xml b/app/code/Magento/Captcha/etc/adminhtml/events.xml index 984e5e9e29f4e..7fcadbfd8f2ff 100644 --- a/app/code/Magento/Captcha/etc/adminhtml/events.xml +++ b/app/code/Magento/Captcha/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/adminhtml/routes.xml b/app/code/Magento/Captcha/etc/adminhtml/routes.xml index e06b87beef772..6b6b6717c489a 100644 --- a/app/code/Magento/Captcha/etc/adminhtml/routes.xml +++ b/app/code/Magento/Captcha/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/adminhtml/system.xml b/app/code/Magento/Captcha/etc/adminhtml/system.xml index dc4c737597cce..88f0ae27f91c7 100644 --- a/app/code/Magento/Captcha/etc/adminhtml/system.xml +++ b/app/code/Magento/Captcha/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/config.xml b/app/code/Magento/Captcha/etc/config.xml index a068485910a77..d969626d73144 100644 --- a/app/code/Magento/Captcha/etc/config.xml +++ b/app/code/Magento/Captcha/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/crontab.xml b/app/code/Magento/Captcha/etc/crontab.xml index 846a15cbdbec6..d3d6e30e1a03a 100644 --- a/app/code/Magento/Captcha/etc/crontab.xml +++ b/app/code/Magento/Captcha/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/crontab/di.xml b/app/code/Magento/Captcha/etc/crontab/di.xml index fd57ded2fb92b..f3086b469842b 100644 --- a/app/code/Magento/Captcha/etc/crontab/di.xml +++ b/app/code/Magento/Captcha/etc/crontab/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/di.xml b/app/code/Magento/Captcha/etc/di.xml index 0bb7660f27a6b..db624420ba647 100644 --- a/app/code/Magento/Captcha/etc/di.xml +++ b/app/code/Magento/Captcha/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/events.xml b/app/code/Magento/Captcha/etc/events.xml index 274058ec98e82..4223c4a2a3256 100644 --- a/app/code/Magento/Captcha/etc/events.xml +++ b/app/code/Magento/Captcha/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/frontend/di.xml b/app/code/Magento/Captcha/etc/frontend/di.xml index d15f8d5914998..209f9beb71a04 100644 --- a/app/code/Magento/Captcha/etc/frontend/di.xml +++ b/app/code/Magento/Captcha/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/frontend/events.xml b/app/code/Magento/Captcha/etc/frontend/events.xml index e1441f0311ee8..dfa0d1b428557 100644 --- a/app/code/Magento/Captcha/etc/frontend/events.xml +++ b/app/code/Magento/Captcha/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/etc/frontend/routes.xml b/app/code/Magento/Captcha/etc/frontend/routes.xml index 255f4551daf5d..d4bbe64821a91 100644 --- a/app/code/Magento/Captcha/etc/frontend/routes.xml +++ b/app/code/Magento/Captcha/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Captcha/etc/module.xml b/app/code/Magento/Captcha/etc/module.xml index 1703142e54133..698604928afb6 100644 --- a/app/code/Magento/Captcha/etc/module.xml +++ b/app/code/Magento/Captcha/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/registration.php b/app/code/Magento/Captcha/registration.php index a8fce947e6697..488ac412a8926 100644 --- a/app/code/Magento/Captcha/registration.php +++ b/app/code/Magento/Captcha/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Captcha/view/adminhtml/layout/adminhtml_auth_login.xml b/app/code/Magento/Captcha/view/adminhtml/layout/adminhtml_auth_login.xml index 3cb5ffbbf5ae3..8c093257f1790 100644 --- a/app/code/Magento/Captcha/view/adminhtml/layout/adminhtml_auth_login.xml +++ b/app/code/Magento/Captcha/view/adminhtml/layout/adminhtml_auth_login.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml b/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml index 3ec8f108bc18d..ffffcc4196bb1 100644 --- a/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml +++ b/app/code/Magento/Captcha/view/adminhtml/templates/default.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Captcha/view/frontend/layout/contact_index_index.xml b/app/code/Magento/Captcha/view/frontend/layout/contact_index_index.xml index 9e31eea8aaeba..1460d8fac6974 100644 --- a/app/code/Magento/Captcha/view/frontend/layout/contact_index_index.xml +++ b/app/code/Magento/Captcha/view/frontend/layout/contact_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/view/frontend/layout/customer_account_create.xml b/app/code/Magento/Captcha/view/frontend/layout/customer_account_create.xml index 573af66d5bd31..cd72cc5857b83 100644 --- a/app/code/Magento/Captcha/view/frontend/layout/customer_account_create.xml +++ b/app/code/Magento/Captcha/view/frontend/layout/customer_account_create.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/view/frontend/layout/customer_account_edit.xml b/app/code/Magento/Captcha/view/frontend/layout/customer_account_edit.xml index 875479c49954c..9700e88006f10 100644 --- a/app/code/Magento/Captcha/view/frontend/layout/customer_account_edit.xml +++ b/app/code/Magento/Captcha/view/frontend/layout/customer_account_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/view/frontend/layout/customer_account_forgotpassword.xml b/app/code/Magento/Captcha/view/frontend/layout/customer_account_forgotpassword.xml index dc92c7c3548bc..1f25fa040b591 100644 --- a/app/code/Magento/Captcha/view/frontend/layout/customer_account_forgotpassword.xml +++ b/app/code/Magento/Captcha/view/frontend/layout/customer_account_forgotpassword.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/view/frontend/layout/customer_account_login.xml b/app/code/Magento/Captcha/view/frontend/layout/customer_account_login.xml index bcabf0adccc26..3a24e44fd1afe 100644 --- a/app/code/Magento/Captcha/view/frontend/layout/customer_account_login.xml +++ b/app/code/Magento/Captcha/view/frontend/layout/customer_account_login.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/view/frontend/layout/default.xml b/app/code/Magento/Captcha/view/frontend/layout/default.xml index 9d6a234514855..43a770c54c0ca 100644 --- a/app/code/Magento/Captcha/view/frontend/layout/default.xml +++ b/app/code/Magento/Captcha/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Captcha/view/frontend/requirejs-config.js b/app/code/Magento/Captcha/view/frontend/requirejs-config.js index 72f7d627b8707..ff1d9f1acc7b1 100644 --- a/app/code/Magento/Captcha/view/frontend/requirejs-config.js +++ b/app/code/Magento/Captcha/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,4 +9,4 @@ var config = { captcha: 'Magento_Captcha/captcha' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Captcha/view/frontend/templates/default.phtml b/app/code/Magento/Captcha/view/frontend/templates/default.phtml index d97d2922c02cb..d8e11113d7707 100644 --- a/app/code/Magento/Captcha/view/frontend/templates/default.phtml +++ b/app/code/Magento/Captcha/view/frontend/templates/default.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/Api/AttributeSetFinderInterface.php b/app/code/Magento/Catalog/Api/AttributeSetFinderInterface.php index 4dabce697b30f..c7df36623ff83 100644 --- a/app/code/Magento/Catalog/Api/AttributeSetFinderInterface.php +++ b/app/code/Magento/Catalog/Api/AttributeSetFinderInterface.php @@ -1,7 +1,7 @@ _getStore(); $collection = $this->_productFactory->create()->getCollection()->addAttributeToSelect( 'sku' @@ -184,6 +182,9 @@ protected function _prepareCollection() $this->setCollection($collection); $this->getCollection()->addWebsiteNamesToResult(); + + parent::_prepareCollection(); + return $this; } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Apply.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Apply.php index 227d08d0a045a..3d70d0a94fe14 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Apply.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Apply.php @@ -1,6 +1,6 @@ _filesystem->getDirectoryRead(DirectoryList::MEDIA); + $mediaDir = $this->_filesystem->getDirectoryRead(DirectoryList::MEDIA); $images = $this->sortImagesByPosition($value['images']); foreach ($images as &$image) { $image['url'] = $this->_mediaConfig->getMediaUrl($image['file']); - $fileHandler = $directory->stat($this->_mediaConfig->getMediaPath($image['file'])); - $image['size'] = $fileHandler['size']; + try { + $fileHandler = $mediaDir->stat($this->_mediaConfig->getMediaPath($image['file'])); + $image['size'] = $fileHandler['size']; + } catch (FileSystemException $e) { + $image['url'] = $this->getImageHelper()->getDefaultPlaceholderUrl('small_image'); + $image['size'] = 0; + $this->_logger->warning($e); + } } return $this->_jsonEncoder->encode($images); } @@ -227,4 +239,17 @@ public function getImageTypesJson() { return $this->_jsonEncoder->encode($this->getImageTypes()); } + + /** + * @return \Magento\Catalog\Helper\Image + * @deprecated + */ + private function getImageHelper() + { + if ($this->imageHelper === null) { + $this->imageHelper = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\Catalog\Helper\Image'); + } + return $this->imageHelper; + } } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Image.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Image.php index 8fc1e26f0cb7f..03ccd4135355c 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Image.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Image.php @@ -1,6 +1,6 @@ getLayout()->getBlock('breadcrumbs')) { $breadcrumbsBlock->addCrumb( 'home', @@ -64,7 +65,6 @@ protected function _prepareLayout() ] ); - $title = []; $path = $this->_catalogData->getBreadcrumbPath(); foreach ($path as $name => $breadcrumb) { @@ -73,7 +73,18 @@ protected function _prepareLayout() } $this->pageConfig->getTitle()->set(join($this->getTitleSeparator(), array_reverse($title))); + + return parent::_prepareLayout(); + } + + $path = $this->_catalogData->getBreadcrumbPath(); + + foreach ($path as $name => $breadcrumb) { + $title[] = $breadcrumb['label']; } + + $this->pageConfig->getTitle()->set(join($this->getTitleSeparator(), array_reverse($title))); + return parent::_prepareLayout(); } } diff --git a/app/code/Magento/Catalog/Block/Category/Plugin/PriceBoxTags.php b/app/code/Magento/Catalog/Block/Category/Plugin/PriceBoxTags.php index aed1624b955f6..e16485fc3425e 100644 --- a/app/code/Magento/Catalog/Block/Category/Plugin/PriceBoxTags.php +++ b/app/code/Magento/Catalog/Block/Category/Plugin/PriceBoxTags.php @@ -1,6 +1,6 @@ true, 'display_minimal_price' => true, - 'zone' => \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST + 'zone' => \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST, + 'list_category_page' => true ] ); } @@ -372,10 +373,14 @@ public function getProductPrice(\Magento\Catalog\Model\Product $product) } /** + * Specifies that price rendering should be done for the list of products + * i.e. rendering happens in the scope of product list, but not single product + * * @return \Magento\Framework\Pricing\Render */ protected function getPriceRender() { - return $this->getLayout()->getBlock('product.price.render.default'); + return $this->getLayout()->getBlock('product.price.render.default') + ->setData('is_product_list', true); } } diff --git a/app/code/Magento/Catalog/Block/Product/NewProduct.php b/app/code/Magento/Catalog/Block/Product/NewProduct.php index 73a9df1bf3822..11bb639ac2a5b 100644 --- a/app/code/Magento/Catalog/Block/Product/NewProduct.php +++ b/app/code/Magento/Catalog/Block/Product/NewProduct.php @@ -1,6 +1,6 @@ _compareProduct; + } +} diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Item/Block.php b/app/code/Magento/Catalog/Block/Product/ProductList/Item/Block.php new file mode 100644 index 0000000000000..3bc2b85dff5ca --- /dev/null +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Item/Block.php @@ -0,0 +1,38 @@ +product = $product; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getProduct() + { + return $this->product; + } +} diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Item/Container.php b/app/code/Magento/Catalog/Block/Product/ProductList/Item/Container.php new file mode 100644 index 0000000000000..3d9c72b7825b6 --- /dev/null +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Item/Container.php @@ -0,0 +1,31 @@ +getLayout(); + if ($layout) { + $name = $this->getNameInLayout(); + foreach ($layout->getChildBlocks($name) as $child) { + if ($child instanceof ProductAwareInterface) { + $child->setProduct($this->getProduct()); + } + } + } + return parent::getChildHtml($alias, $useCache); + } +} diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Promotion.php b/app/code/Magento/Catalog/Block/Product/ProductList/Promotion.php index 7f1e6f8e025a2..c6176bce8a08a 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Promotion.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Promotion.php @@ -1,6 +1,6 @@ getProduct(); + return $this->_compareProduct->getPostDataParams($product); + } +} diff --git a/app/code/Magento/Catalog/Block/Product/View/Additional.php b/app/code/Magento/Catalog/Block/Product/View/Additional.php index 13d68910c017d..464cf55aeb4f7 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Additional.php +++ b/app/code/Magento/Catalog/Block/Product/View/Additional.php @@ -1,6 +1,6 @@ priceCurrency->convertAndFormat($value); } - if (is_string($value) && strlen($value)) { + if (($value instanceof Phrase || is_string($value)) && strlen($value)) { $data[$attribute->getAttributeCode()] = [ 'label' => __($attribute->getStoreLabel()), 'value' => $value, diff --git a/app/code/Magento/Catalog/Block/Product/View/BaseImage.php b/app/code/Magento/Catalog/Block/Product/View/BaseImage.php index 4b9470798df38..6c73174d9f9b9 100644 --- a/app/code/Magento/Catalog/Block/Product/View/BaseImage.php +++ b/app/code/Magento/Catalog/Block/Product/View/BaseImage.php @@ -1,6 +1,6 @@ getFrontendInput() == 'multiselect') { // Check if 'Change' checkbox has been checked by admin for this attribute - $isChanged = (bool)$this->getRequest()->getPost($attributeCode . '_checkbox'); + $isChanged = (bool)$this->getRequest()->getPost('toggle_' . $attributeCode); if (!$isChanged) { unset($attributesData[$attributeCode]); continue; diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php index 2bc7fc2543863..8f867459c8836 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php @@ -1,7 +1,7 @@ resultJsonFactory = $resultJsonFactory; $this->layoutFactory = $layoutFactory; + $this->multipleAttributeList = $multipleAttributeList; } /** * @return \Magento\Framework\Controller\ResultInterface + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function execute() { @@ -89,9 +99,37 @@ public function execute() $response->setHtmlMessage($layout->getMessagesBlock()->getGroupedHtml()); } } + + $multipleOption = $this->getRequest()->getParam('frontend_input'); + $multipleOption = null === $multipleOption ? 'select' : $multipleOption; + if (isset($this->multipleAttributeList[$multipleOption]) && null !== $multipleOption) { + $this->checkUniqueOption( + $response, + $this->getRequest()->getParam($this->multipleAttributeList[$multipleOption]) + ); + } + return $this->resultJsonFactory->create()->setJsonData($response->toJson()); } + /** + * Throws Exception if not unique values into options + * @param array $optionsValues + * @param array $deletedOptions + * @return bool + */ + private function isUniqueAdminValues(array $optionsValues, array $deletedOptions) + { + $adminValues = []; + foreach ($optionsValues as $optionKey => $values) { + if (!(isset($deletedOptions[$optionKey]) and $deletedOptions[$optionKey] === '1')) { + $adminValues[] = reset($values); + } + } + $uniqueValues = array_unique($adminValues); + return ($uniqueValues === $adminValues); + } + /** * Set message to response object * @@ -107,4 +145,16 @@ private function setMessageToResponse($response, $messages) } return $response->setData($messageKey, $messages); } + + /** + * @param DataObject $response + * @param array|null $options + */ + private function checkUniqueOption(DataObject $response, array $options = null) + { + if (is_array($options) && !$this->isUniqueAdminValues($options['value'], $options['delete'])) { + $this->setMessageToResponse($response, [__('The value of Admin must be unique.')]); + $response->setError(true); + } + } } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php index 7004413c5c569..05fe939252184 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php @@ -1,7 +1,7 @@ request = $request; $this->storeManager = $storeManager; @@ -98,6 +105,8 @@ public function __construct( $this->productLinks = $productLinks; $this->jsHelper = $jsHelper; $this->dateFilter = $dateFilter; + $this->linkTypeProvider = $linkTypeProvider ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Catalog\Model\Product\LinkTypeProvider::class); } /** @@ -247,11 +256,17 @@ protected function setProductLinks(\Magento\Catalog\Model\Product $product) $product = $this->productLinks->initializeLinks($product, $links); $productLinks = $product->getProductLinks(); - $linkTypes = [ - 'related' => $product->getRelatedReadonly(), - 'upsell' => $product->getUpsellReadonly(), - 'crosssell' => $product->getCrosssellReadonly() - ]; + $linkTypes = []; + + /** @var \Magento\Catalog\Api\Data\ProductLinkTypeInterface $linkTypeObject */ + foreach ($this->linkTypeProvider->getItems() as $linkTypeObject) { + $linkTypes[$linkTypeObject->getName()] = $product->getData($linkTypeObject->getName() . '_readonly'); + } + + // skip linkTypes that were already processed on initializeLinks plugins + foreach ($productLinks as $productLink) { + unset($linkTypes[$productLink->getLinkType()]); + } foreach ($linkTypes as $linkType => $readonly) { if (isset($links[$linkType]) && !$readonly) { diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/HandlerFactory.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/HandlerFactory.php index 09d324bc1d5aa..1aa81f50d822d 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/HandlerFactory.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/HandlerFactory.php @@ -1,6 +1,6 @@ getAllIds(); $storeId = (int) $this->getRequest()->getParam('store', 0); $status = (int) $this->getRequest()->getParam('status'); + $filters = (array)$this->getRequest()->getParam('filters', []); + + if (isset($filters['store_id'])) { + $storeId = (int)$filters['store_id']; + } try { $this->_validateMassStatus($productIds, $status); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php index a5153a7342674..ec85b9e391afb 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php @@ -1,7 +1,7 @@ stockFilter = $stockFilter; parent::__construct($context, $productBuilder); $this->resultPageFactory = $resultPageFactory; $this->resultForwardFactory = $resultForwardFactory; + $this->storeManager = $storeManager ?: $this->_objectManager->get( + \Magento\Store\Model\StoreManagerInterface::class + ); } /** @@ -60,6 +70,10 @@ public function execute() } $product = $this->productBuilder->build($this->getRequest()); + + $store = $this->storeManager->getStore($product->getStoreId()); + $this->storeManager->setCurrentStore($store->getCode()); + $this->_eventManager->dispatch('catalog_product_new_action', ['product' => $product]); /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Options.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Options.php index b7c0cb2232426..60482fd1c01e9 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Options.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Options.php @@ -1,7 +1,7 @@ storeManager = $storeManager ?: $this->_objectManager->get( + StoreManagerInterface::class + ); + } + /** * {@inheritdoc} */ @@ -23,11 +47,15 @@ public function execute() $product = $this->productBuilder->build($this->getRequest()); + $store = $this->storeManager->getStore($product->getStoreId()); + $this->storeManager->setCurrentStore($store->getCode()); + /** @var \Magento\Framework\View\Result\Layout $resultLayout */ $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT); $resultLayout->getLayout()->getUpdate()->addHandle(['catalog_product_' . $product->getTypeId()]); $resultLayout->getLayout()->getUpdate()->removeHandle('default'); $resultLayout->setHeader('Content-Type', 'application/json', true); + return $resultLayout; } } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php index 97f5935004ca5..61d2c5cc77831 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php @@ -1,7 +1,7 @@ resource = $resource; + $this->attributeRepository = $attributeRepository; + $this->scopeConfig = $scopeConfig; + } + + /** + * Delete all price values for non-admin stores if PRICE_SCOPE is global + * + * @return void + */ + public function execute() + { + $priceScope = $this->scopeConfig->getValue(Store::XML_PATH_PRICE_SCOPE); + if ($priceScope == Store::PRICE_SCOPE_GLOBAL) { + /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $priceAttribute */ + $priceAttribute = $this->attributeRepository + ->get(ProductAttributeInterface::ENTITY_TYPE_CODE, ProductAttributeInterface::CODE_PRICE); + $connection = $this->resource->getConnection(); + $conditions = [ + $connection->quoteInto('attribute_id = ?', $priceAttribute->getId()), + $connection->quoteInto('store_id != ?', Store::DEFAULT_STORE_ID), + ]; + + $connection->delete( + $priceAttribute->getBackend()->getTable(), + $conditions + ); + } + } +} diff --git a/app/code/Magento/Catalog/Cron/RefreshSpecialPrices.php b/app/code/Magento/Catalog/Cron/RefreshSpecialPrices.php index e3a63e0367328..5e04b026db3d4 100644 --- a/app/code/Magento/Catalog/Cron/RefreshSpecialPrices.php +++ b/app/code/Magento/Catalog/Cron/RefreshSpecialPrices.php @@ -1,6 +1,6 @@ getEncodedUrl($this->_getUrl('catalog/product_compare')); $data = [ - \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => $listCleanUrl, - 'product' => $product->getId() + \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => '', + 'product' => $product->getId(), ]; return $this->postHelper->getPostData($this->getRemoveUrl(), $data); } @@ -253,9 +252,8 @@ public function getClearListUrl() */ public function getPostDataClearList() { - $refererUrl = $this->_getRequest()->getServer('HTTP_REFERER'); $params = [ - \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => $this->urlEncoder->encode($refererUrl) + \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => '', ]; return $this->postHelper->getPostData($this->getClearListUrl(), $params); } diff --git a/app/code/Magento/Catalog/Helper/Product/Composite.php b/app/code/Magento/Catalog/Helper/Product/Composite.php index fcd710ad1ec84..5e519540c78ca 100644 --- a/app/code/Magento/Catalog/Helper/Product/Composite.php +++ b/app/code/Magento/Catalog/Helper/Product/Composite.php @@ -1,6 +1,6 @@ _productIndexerHelper->getAttribute('status'); @@ -263,7 +267,7 @@ protected function _fillTemporaryFlatTable(array $tables, $storeId, $valueFieldS $select->joinLeft( $temporaryTableName, - "e.entity_id = " . $temporaryTableName . ".entity_id", + "e.${linkField} = ${temporaryTableName}.${linkField}", $columnsNames ); $allColumns = array_merge($allColumns, $columnsNames); @@ -277,7 +281,7 @@ protected function _fillTemporaryFlatTable(array $tables, $storeId, $valueFieldS if (!empty($columnValueNames)) { $select->joinLeft( $temporaryValueTableName, - "e.${linkField} = " . $temporaryValueTableName . ".entity_id", + "e.${linkField} = " . $temporaryValueTableName . ".${linkField}", $columnValueNames ); $allColumns = array_merge($allColumns, $columnValueNames); diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/IndexerConfigData.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/IndexerConfigData.php index 60394766f4b52..b06b0a547920a 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/IndexerConfigData.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/IndexerConfigData.php @@ -1,6 +1,6 @@ tableInstance = $connection->newTable($tableName); + } + + /** + * Adds column to table. + * + * $options contains additional options for columns. Supported values are: + * - 'unsigned', for number types only. Default: FALSE. + * - 'precision', for numeric and decimal only. Default: taken from $size, if not set there then 0. + * - 'scale', for numeric and decimal only. Default: taken from $size, if not set there then 10. + * - 'default'. Default: not set. + * - 'nullable'. Default: TRUE. + * - 'primary', add column to primary index. Default: do not add. + * - 'primary_position', only for column in primary index. Default: count of primary columns + 1. + * - 'identity' or 'auto_increment'. Default: FALSE. + * + * @param string $name the column name + * @param string $type the column data type + * @param string|int|array $size the column length + * @param array $options array of additional options + * @param string $comment column description + * @return $this + * @throws \Zend_Db_Exception + */ + public function addColumn($name, $type, $size = null, $options = [], $comment = null) + { + $this->tableInstance->addColumn($name, $type, $size, $options, $comment); + return $this; + } + + /** + * @return \Magento\Framework\DB\Ddl\Table + */ + public function getTable() + { + return $this->tableInstance; + } +} diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Table/BuilderInterface.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Table/BuilderInterface.php new file mode 100644 index 0000000000000..3651821ae10ac --- /dev/null +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Table/BuilderInterface.php @@ -0,0 +1,40 @@ +_productIndexerHelper = $productIndexerHelper; $this->resource = $resource; $this->_connection = $resource->getConnection(); + $this->tableBuilderFactory = $tableBuilderFactory ?: + ObjectManager::getInstance()->get(BuilderInterfaceFactory::class); } /** @@ -123,17 +133,27 @@ protected function _createTemporaryTable($tableName, array $columns, $valueField $valueTables = []; if (!empty($columns)) { $valueTableName = $tableName . $valueFieldSuffix; - $temporaryTable = $this->_connection->newTable($tableName); - $valueTemporaryTable = $this->_connection->newTable($valueTableName); + $temporaryTableBuilder = $this->tableBuilderFactory->create( + [ + 'connection' => $this->_connection, + 'tableName' => $tableName + ] + ); + $valueTemporaryTableBuilder = $this->tableBuilderFactory->create( + [ + 'connection' => $this->_connection, + 'tableName' => $valueTableName + ] + ); $flatColumns = $this->_productIndexerHelper->getFlatColumns(); - $temporaryTable->addColumn('entity_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER); + $temporaryTableBuilder->addColumn('entity_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER); - $temporaryTable->addColumn('type_id', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT); + $temporaryTableBuilder->addColumn('type_id', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT); - $temporaryTable->addColumn('attribute_set_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER); + $temporaryTableBuilder->addColumn('attribute_set_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER); - $valueTemporaryTable->addColumn('entity_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER); + $valueTemporaryTableBuilder->addColumn('entity_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER); /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ foreach ($columns as $columnName => $attribute) { @@ -145,7 +165,7 @@ protected function _createTemporaryTable($tableName, array $columns, $valueField $column = $column[$attributeCode]; } - $temporaryTable->addColumn( + $temporaryTableBuilder->addColumn( $columnName, $column['type'], isset($column['length']) ? $column['length'] : null @@ -154,7 +174,7 @@ protected function _createTemporaryTable($tableName, array $columns, $valueField $columnValueName = $attributeCode . $valueFieldSuffix; if (isset($flatColumns[$columnValueName])) { $columnValue = $flatColumns[$columnValueName]; - $valueTemporaryTable->addColumn( + $valueTemporaryTableBuilder->addColumn( $columnValueName, $columnValue['type'], isset($columnValue['length']) ? $columnValue['length'] : null @@ -162,11 +182,11 @@ protected function _createTemporaryTable($tableName, array $columns, $valueField } } $this->_connection->dropTemporaryTable($tableName); - $this->_connection->createTemporaryTable($temporaryTable); + $this->_connection->createTemporaryTable($temporaryTableBuilder->getTable()); - if (count($valueTemporaryTable->getColumns()) > 1) { + if (count($valueTemporaryTableBuilder->getTable()->getColumns()) > 1) { $this->_connection->dropTemporaryTable($valueTableName); - $this->_connection->createTemporaryTable($valueTemporaryTable); + $this->_connection->createTemporaryTable($valueTemporaryTableBuilder->getTable()); $valueTables[$valueTableName] = $valueTableName; } } @@ -197,7 +217,8 @@ protected function _fillTemporaryEntityTable($tableName, array $columns, array $ if (!empty($columns)) { $select = $this->_connection->select(); $temporaryEntityTable = $this->_getTemporaryTableName($tableName); - $idsColumns = ['entity_id', 'type_id', 'attribute_set_id']; + $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class); + $idsColumns = array_unique([$metadata->getLinkField(), 'entity_id', 'type_id', 'attribute_set_id']); $columns = array_merge($idsColumns, array_keys($columns)); @@ -261,7 +282,7 @@ protected function _fillTemporaryTable( ); $temporaryTableName = $this->_getTemporaryTableName($tableName); $temporaryValueTableName = $temporaryTableName . $valueFieldSuffix; - $keyColumn = ['entity_id']; + $keyColumn = array_unique([$metadata->getLinkField(), 'entity_id']); $columns = array_merge($keyColumn, array_keys($columnsList)); $valueColumns = $keyColumn; $flatColumns = $this->_productIndexerHelper->getFlatColumns(); @@ -339,8 +360,8 @@ protected function _fillTemporaryTable( private function getMetadataPool() { if (null === $this->metadataPool) { - $this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance() - ->get('Magento\Framework\EntityManager\MetadataPool'); + $this->metadataPool = ObjectManager::getInstance() + ->get(\Magento\Framework\EntityManager\MetadataPool::class); } return $this->metadataPool; } diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableData.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableData.php index a5a1b7d808f58..8f12fbfd358dc 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableData.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/TableData.php @@ -1,6 +1,6 @@ _catalogProduct->getSkipSaleableCheck()) { + return true; + } + if (($this->getOrigData('status') != $this->getData('status')) + || $this->isStockStatusChanged()) { + $this->unsetData('salable'); + } + + if ($this->hasData('salable')) { + return $this->getData('salable'); + } $this->_eventManager->dispatch('catalog_product_is_salable_before', ['product' => $this]); $salable = $this->isAvailable(); @@ -1623,7 +1633,8 @@ public function isSalable() 'catalog_product_is_salable_after', ['product' => $this, 'salable' => $object] ); - return $object->getIsSalable(); + $this->setData('salable', $object->getIsSalable()); + return $this->getData('salable'); } /** @@ -1633,7 +1644,7 @@ public function isSalable() */ public function isAvailable() { - return $this->getTypeInstance()->isSalable($this) || $this->_catalogProduct->getSkipSaleableCheck(); + return $this->_catalogProduct->getSkipSaleableCheck() || $this->getTypeInstance()->isSalable($this); } /** @@ -1906,14 +1917,18 @@ public function addOption(Product\Option $option) */ public function getOptionById($optionId) { - /** @var \Magento\Catalog\Model\Product\Option $option */ - foreach ($this->getOptions() as $option) { - if ($option->getId() == $optionId) { - return $option; + $result = null; + if (is_array($this->getOptions())) { + /** @var \Magento\Catalog\Model\Product\Option $option */ + foreach ($this->getOptions() as $option) { + if ($option->getId() == $optionId) { + $result = $option; + break; + } } } - return null; + return $result; } /** @@ -2609,4 +2624,14 @@ private function getMediaGalleryProcessor() } return $this->mediaGalleryProcessor; } + + /** + * Set the associated products + * @param array $productIds + * @return void + */ + public function setAssociatedProductIds(array $productIds) + { + $this->getExtensionAttributes()->setConfigurableProductLinks($productIds); + } } diff --git a/app/code/Magento/Catalog/Model/Product/Action.php b/app/code/Magento/Catalog/Model/Product/Action.php index f1d9fea22e707..6484f477c0ab6 100644 --- a/app/code/Magento/Catalog/Model/Product/Action.php +++ b/app/code/Magento/Catalog/Model/Product/Action.php @@ -1,6 +1,6 @@ getData($this->getAttribute()->getAttributeCode()); - /** - * Orig value is only for existing objects - */ - $oridData = $object->getOrigData(); - $origValueExist = $oridData && array_key_exists($this->getAttribute()->getAttributeCode(), $oridData); - if ($object->getStoreId() != 0 || !$value || $origValueExist) { - return $this; - } - - if ($this->getAttribute()->getIsGlobal() == ScopedAttributeInterface::SCOPE_WEBSITE) { - $baseCurrency = $this->_config->getValue( - \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE, - 'default' - ); - - $storeIds = $object->getStoreIds(); - if (is_array($storeIds)) { - foreach ($storeIds as $storeId) { - $storeCurrency = $this->_storeManager->getStore($storeId)->getBaseCurrencyCode(); - if ($storeCurrency == $baseCurrency) { - continue; - } - $rate = $this->_currencyFactory->create()->load($baseCurrency)->getRate($storeCurrency); - if (!$rate) { - $rate = 1; - } - $newValue = $value * $rate; - $object->addAttributeUpdate($this->getAttribute()->getAttributeCode(), $newValue, $storeId); + /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ + $attribute = $this->getAttribute(); + $attributeCode = $attribute->getAttributeCode(); + $value = $object->getData($attributeCode); + if ($value && $value != $object->getOrigData($attributeCode)) { + if ($attribute->isScopeWebsite()) { + foreach ((array)$object->getWebsiteStoreIds() as $storeId) { + /** @var $object \Magento\Catalog\Model\Product */ + $object->addAttributeUpdate($attributeCode, $value, $storeId); } } } diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php index 327729cf83695..be98147abfc85 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php @@ -1,6 +1,6 @@ getAttribute(); $entity = $attribute->getEntity(); - $increment = $this->_getLastSimilarAttributeValueIncrement($attribute, $object); $attributeValue = $object->getData($attribute->getAttributeCode()); + $increment = null; while (!$entity->checkAttributeUniqueValue($attribute, $object)) { + if ($increment === null) { + $increment = $this->_getLastSimilarAttributeValueIncrement($attribute, $object); + } $sku = trim($attributeValue); if (strlen($sku . '-' . ++$increment) > self::SKU_MAX_LENGTH) { $sku = substr($sku, 0, -strlen($increment) - 1); diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php index 5c3fd4730aaed..b1b81512b53c4 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php @@ -1,6 +1,6 @@ getStockData() !== null || $stockData !== null) { + if ($object->getStockData() !== null && $stockData !== null) { $object->setStockData(array_replace((array)$object->getStockData(), (array)$stockData)); } $object->unsetData($this->getAttribute()->getAttributeCode()); diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php index fc0fc07d4d524..73e1c472e44e8 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php @@ -1,6 +1,6 @@ - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Catalog\Model\Product\Attribute; diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Management.php b/app/code/Magento/Catalog/Model/Product/Attribute/Management.php index fa9b2ddee3cfe..4529b61147402 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Management.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Management.php @@ -1,7 +1,7 @@ - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Catalog\Model\Product\Attribute; diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Repository.php b/app/code/Magento/Catalog/Model/Product/Attribute/Repository.php index 3d5e49985d27b..a6fe00107622f 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Repository.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Repository.php @@ -1,7 +1,7 @@ setDefaultFrontendLabel($frontendLabel); } - if (!$attribute->getIsUserDefined()) { - // Unset attribute field for system attributes - $attribute->setApplyTo(null); - } } else { $attribute->setAttributeId(null); diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php b/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php index d69e5a64939e9..e5ef94968d441 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/SetManagement.php @@ -1,7 +1,7 @@ mediaConfig->getMediaAttributeCodes() as $mediaAttrCode) { + foreach ($this->getMediaAttributeCodes() as $mediaAttrCode) { $attrData = $product->getData($mediaAttrCode); - + if (empty($attrData) && empty($clearImages) && empty($newImages) && empty($existImages)) { + continue; + } if (in_array($attrData, $clearImages)) { $product->setData($mediaAttrCode, 'no_selection'); } @@ -393,4 +400,17 @@ protected function copyImage($file) ); } } + + /** + * Get Media Attribute Codes cached value + * + * @return array + */ + private function getMediaAttributeCodes() + { + if ($this->mediaAttributeCodes === null) { + $this->mediaAttributeCodes = $this->mediaConfig->getMediaAttributeCodes(); + } + return $this->mediaAttributeCodes; + } } diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/Entry.php b/app/code/Magento/Catalog/Model/Product/Gallery/Entry.php index cbe876561ad2e..8cfed2631994e 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/Entry.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/Entry.php @@ -1,7 +1,7 @@ $existingEntry) { if ($existingEntry->getId() == $entry->getId()) { $found = true; + if ($entry->getFile()) { + $entry->setId(null); + } $existingMediaGalleryEntries[$key] = $entry; break; } diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/MimeTypeExtensionMap.php b/app/code/Magento/Catalog/Model/Product/Gallery/MimeTypeExtensionMap.php index e116e1b4f1cc8..4242539b9fe8b 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/MimeTypeExtensionMap.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/MimeTypeExtensionMap.php @@ -1,7 +1,7 @@ resourceModel->loadProductGalleryByAttributeId( $entity, $this->getAttribute()->getAttributeId() ); - foreach ($mediaEntries as $mediaEntry) { - foreach ($localAttributes as $localAttribute) { - if ($mediaEntry[$localAttribute] === null) { - $mediaEntry[$localAttribute] = $this->findDefaultValue($localAttribute, $mediaEntry); - } - } + $this->addMediaDataToProduct( + $entity, + $mediaEntries + ); + + return $entity; + } + + /** + * @param Product $product + * @param array $mediaEntries + * @return void + */ + public function addMediaDataToProduct(Product $product, array $mediaEntries) + { + $attrCode = $this->getAttribute()->getAttributeCode(); + $value = []; + $value['images'] = []; + $value['values'] = []; + foreach ($mediaEntries as $mediaEntry) { + $mediaEntry = $this->substituteNullsWithDefaultValues($mediaEntry); $value['images'][$mediaEntry['value_id']] = $mediaEntry; } + $product->setData($attrCode, $value); + } - $entity->setData( - $this->getAttribute()->getAttributeCode(), - $value - ); + /** + * @param array $rawData + * @return array + */ + private function substituteNullsWithDefaultValues(array $rawData) + { + $processedData = []; + foreach ($rawData as $key => $rawValue) { + if (null !== $rawValue) { + $processedValue = $rawValue; + } elseif (isset($rawData[$key . '_default'])) { + $processedValue = $rawData[$key . '_default']; + } else { + $processedValue = null; + } + $processedData[$key] = $processedValue; + } - return $entity; + return $processedData; } /** @@ -93,6 +122,7 @@ public function getAttribute() * @param string $key * @param string[] &$image * @return string + * @deprecated */ protected function findDefaultValue($key, &$image) { diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/UpdateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/UpdateHandler.php index 45a6cf3db5f48..8c2d4a53a7722 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/UpdateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/UpdateHandler.php @@ -1,6 +1,6 @@ _catalogProductMediaConfig->getBaseMediaPath(), 'cache', - $this->_storeManager->getStore()->getId(), - $path[] = $this->getDestinationSubdir(), + $this->getDestinationSubdir(), ]; if (!empty($this->_width) || !empty($this->_height)) { $path[] = "{$this->_width}x{$this->_height}"; diff --git a/app/code/Magento/Catalog/Model/Product/Image/Cache.php b/app/code/Magento/Catalog/Model/Product/Image/Cache.php index 830e8be2f3852..2a5316583ff6e 100644 --- a/app/code/Magento/Catalog/Model/Product/Image/Cache.php +++ b/app/code/Magento/Catalog/Model/Product/Image/Cache.php @@ -1,6 +1,6 @@ metadataPool = $metadataPool; $this->linkResource = $linkResource; $this->productLinkRepository = $productLinkRepository; @@ -54,12 +53,18 @@ public function __construct( */ public function execute($entityType, $entity) { - /** @var \Magento\Catalog\Api\Data\ProductInterface $entity*/ - foreach ($this->productLinkRepository->getList($entity) as $link) { - $this->productLinkRepository->delete($link); + $link = $entity->getData($this->metadataPool->getMetadata($entityType)->getLinkField()); + if ($this->linkResource->hasProductLinks($link)) { + /** @var \Magento\Catalog\Api\Data\ProductInterface $entity*/ + foreach ($this->productLinkRepository->getList($entity) as $link) { + $this->productLinkRepository->delete($link); + } } - foreach ($entity->getProductLinks() as $link) { - $this->productLinkRepository->save($link); + $productLinks = $entity->getProductLinks(); + if (count($productLinks) > 0) { + foreach ($entity->getProductLinks() as $link) { + $this->productLinkRepository->save($link); + } } return $entity; } diff --git a/app/code/Magento/Catalog/Model/Product/LinkTypeProvider.php b/app/code/Magento/Catalog/Model/Product/LinkTypeProvider.php index 8a878e68957dc..e9f3e490bec57 100644 --- a/app/code/Magento/Catalog/Model/Product/LinkTypeProvider.php +++ b/app/code/Magento/Catalog/Model/Product/LinkTypeProvider.php @@ -2,7 +2,7 @@ /** * Collection of the available product link types * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Catalog\Model\Product; diff --git a/app/code/Magento/Catalog/Model/Product/Media/AttributeManagement.php b/app/code/Magento/Catalog/Model/Product/Media/AttributeManagement.php index 1bcc025fa2e7c..22f7690c8fc10 100644 --- a/app/code/Magento/Catalog/Model/Product/Media/AttributeManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Media/AttributeManagement.php @@ -1,6 +1,6 @@ _itemOptionFactory = $itemOptionFactory; $this->_urlBuilder = $urlBuilder; $this->_escaper = $escaper; $this->_coreFileStorageDatabase = $coreFileStorageDatabase; + $this->filesystem = $filesystem ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Filesystem::class); + $this->_rootDirectory = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA); $this->validatorInfo = $validatorInfo; $this->validatorFile = $validatorFile; parent::__construct($checkoutSession, $scopeConfig, $data); diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php index 71011fe55072d..8d12349af0354 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidateFactory.php @@ -1,6 +1,6 @@ getCanShowPrice() !== false && $salableItem->isSalable(); + } +} diff --git a/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolverInterface.php b/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolverInterface.php new file mode 100644 index 0000000000000..1b540dca770c3 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolverInterface.php @@ -0,0 +1,21 @@ +getChildrenCount()) { $object->setChildrenCount(0); } - + $object->setAttributeSetId( + $object->getAttributeSetId() ?: $this->getEntityType()->getDefaultAttributeSetId() + ); if ($object->isObjectNew()) { if ($object->getPosition() === null) { $object->setPosition($this->_getMaxPosition($object->getPath()) + 1); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php b/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php index 4599fc4a8428a..7d55ebc3e9f91 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category/AggregateCount.php @@ -1,6 +1,6 @@ getData(self::APPLY_TO)) { - if (is_array($this->getData(self::APPLY_TO))) { - return $this->getData(self::APPLY_TO); - } - return explode(',', $this->getData(self::APPLY_TO)); - } else { - return []; + $applyTo = $this->_getData(self::APPLY_TO) ?: []; + if (!is_array($applyTo)) { + $applyTo = explode(',', $applyTo); } + return $applyTo; } /** diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Helper.php b/app/code/Magento/Catalog/Model/ResourceModel/Helper.php index 36dbf0b9739c7..d9490b418c37c 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Helper.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Helper.php @@ -1,6 +1,6 @@ removeAttributeToSelect('price'); + $connection = $this->getConnection(); $select = $this->getSelect(); $joinCond = join( @@ -2070,12 +2090,13 @@ public function addTierPriceData() if ($this->getFlag('tier_price_added')) { return $this; } + $linkField = $this->getConnection()->getAutoIncrementField($this->getTable('catalog_product_entity')); $tierPrices = []; $productIds = []; foreach ($this->getItems() as $item) { - $productIds[] = $item->getId(); - $tierPrices[$item->getId()] = []; + $productIds[] = $item->getData($linkField); + $tierPrices[$item->getData($linkField)] = []; } if (!$productIds) { return $this; @@ -2083,14 +2104,11 @@ public function addTierPriceData() /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ $attribute = $this->getAttribute('tier_price'); - if ($attribute->isScopeGlobal()) { - $websiteId = 0; - } else { - if ($this->getStoreId()) { - $websiteId = $this->_storeManager->getStore($this->getStoreId())->getWebsiteId(); - } + $websiteId = 0; + if (!$attribute->isScopeGlobal() && null !== $this->getStoreId()) { + $websiteId = $this->_storeManager->getStore($this->getStoreId())->getWebsiteId(); } - $linkField = $this->getConnection()->getAutoIncrementField($this->getTable('catalog_product_entity')); + $connection = $this->getConnection(); $columns = [ 'price_id' => 'value_id', @@ -2111,10 +2129,10 @@ public function addTierPriceData() [$linkField, 'qty'] ); - if ($websiteId == '0') { + if ($websiteId == 0) { $select->where('website_id = ?', $websiteId); } else { - $select->where('website_id IN(?)', ['0', $websiteId]); + $select->where('website_id IN(?)', [0, $websiteId]); } foreach ($connection->fetchAll($select) as $row) { @@ -2131,7 +2149,7 @@ public function addTierPriceData() $backend = $attribute->getBackend(); foreach ($this->getItems() as $item) { - $data = $tierPrices[$item->getId()]; + $data = $tierPrices[$item->getData($linkField)]; if (!empty($data) && $websiteId) { $data = $backend->preparePriceData($data, $item->getTypeId(), $websiteId); } @@ -2167,6 +2185,89 @@ public function addPriceDataFieldFilter($comparisonFormat, $fields) return $this; } + /** + * Add media gallery data to loaded items + * + * @return $this + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function addMediaGalleryData() + { + if ($this->getFlag('media_gallery_added')) { + return $this; + } + + if (!$this->count()) { + return $this; + } + + /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ + $attribute = $this->getAttribute('media_gallery'); + $select = $this->getMediaGalleryResource()->createBatchBaseSelect( + $this->getStoreId(), + $attribute->getAttributeId() + ); + + $mediaGalleries = []; + $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField(); + $items = $this->getItems(); + + $select->where('entity.' . $linkField . ' IN (?)', array_map(function ($item) { + return $item->getId(); + }, $items)); + + foreach ($this->getConnection()->fetchAll($select) as $row) { + $mediaGalleries[$row[$linkField]][] = $row; + } + + foreach ($items as $item) { + $mediaEntries = isset($mediaGalleries[$item->getId()]) ? $mediaGalleries[$item->getId()] : []; + $this->getGalleryReadHandler()->addMediaDataToProduct($item, $mediaEntries); + } + + $this->setFlag('media_gallery_added', true); + return $this; + } + + /** + * Get MetadataPool instance + * @return MetadataPool + */ + private function getMetadataPool() + { + if (!$this->metadataPool) { + $this->metadataPool = ObjectManager::getInstance()->get(MetadataPool::class); + } + return $this->metadataPool; + } + + /** + * Retrieve GalleryReadHandler + * + * @return GalleryReadHandler + * @deprecated + */ + protected function getGalleryReadHandler() + { + if ($this->productGalleryReadHandler === null) { + $this->productGalleryReadHandler = ObjectManager::getInstance()->get(GalleryReadHandler::class); + } + return $this->productGalleryReadHandler; + } + + /** + * @deprecated + * @return \Magento\Catalog\Model\ResourceModel\Product\Gallery + */ + private function getMediaGalleryResource() + { + if (null === $this->mediaGalleryResource) { + $this->mediaGalleryResource = ObjectManager::getInstance()->get(Gallery::class); + } + return $this->mediaGalleryResource; + } + /** * Clear collection * diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection/ProductLimitation.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection/ProductLimitation.php index aba330bea0651..28fcb4ab5c405 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection/ProductLimitation.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection/ProductLimitation.php @@ -1,6 +1,6 @@ baseSelectProcessors = $baseSelectProcessors; + } + + /** + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + foreach ($this->baseSelectProcessors as $baseSelectProcessor) { + $select = $baseSelectProcessor->process($select); + } + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Flat.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Flat.php index 56f14d4c12577..2dd445377d6ea 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Flat.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Flat.php @@ -1,6 +1,6 @@ createBatchBaseSelect($storeId, $attributeId); + + $select = $select->where( + 'entity.' . $this->metadata->getLinkField() .' = ?', + $entityId + ); + return $select; + } + + /** + * @param int $storeId + * @param int $attributeId + * @return \Magento\Framework\DB\Select + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function createBatchBaseSelect($storeId, $attributeId) { $linkField = $this->metadata->getLinkField(); @@ -158,7 +177,6 @@ protected function createBaseLoadSelect($entityId, $storeId, $attributeId) [ $mainTableAlias . '.value_id = value.value_id', $this->getConnection()->quoteInto('value.store_id = ?', (int)$storeId), - $this->getConnection()->quoteInto('value.' . $linkField . ' = ?', (int)$entityId) ] ), ['label', 'position', 'disabled'] @@ -168,8 +186,7 @@ protected function createBaseLoadSelect($entityId, $storeId, $attributeId) ' AND ', [ $mainTableAlias . '.value_id = default_value.value_id', - 'default_value.store_id = 0', - $this->getConnection()->quoteInto('default_value.' . $linkField . ' = ?', (int)$entityId) + $this->getConnection()->quoteInto('default_value.store_id = ?', Store::DEFAULT_STORE_ID), ] ), ['label_default' => 'label', 'position_default' => 'position', 'disabled_default' => 'disabled'] @@ -178,9 +195,6 @@ protected function createBaseLoadSelect($entityId, $storeId, $attributeId) $attributeId )->where( $mainTableAlias . '.disabled = 0' - )->where( - 'entity.' . $linkField . ' = ?', - $entityId )->order( $positionCheckSql . ' ' . \Magento\Framework\DB\Select::SQL_ASC ); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/AbstractIndexer.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/AbstractIndexer.php index ec26ad30157ad..33fe4bc378b63 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/AbstractIndexer.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/AbstractIndexer.php @@ -1,6 +1,6 @@ storeManager = $storeManager; + $this->resource = $resourceConnection; + $this->customerSession = $customerSession; + $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); + } + + /** + * {@inheritdoc} + */ + public function build($productId) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $productTable = $this->resource->getTableName('catalog_product_entity'); + + $priceSelect = $this->resource->getConnection()->select() + ->from(['parent' => $productTable], '') + ->joinInner( + ['link' => $this->resource->getTableName('catalog_product_relation')], + "link.parent_id = parent.$linkField", + [] + )->joinInner( + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] + )->joinInner( + ['t' => $this->resource->getTableName('catalog_product_index_price')], + sprintf('t.entity_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + )->where('parent.entity_id = ?', $productId) + ->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()) + ->where('t.customer_group_id = ?', $this->customerSession->getCustomerGroupId()) + ->order('t.min_price ' . Select::SQL_ASC) + ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); + + return [$priceSelect]; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php index 289445ae2daf0..41456945191fa 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php @@ -1,6 +1,6 @@ fetchOne($select, $bind); } + /** + * Check if product has links. + * + * @param int $parentId ID of product + * @return bool + */ + public function hasProductLinks($parentId) + { + $connection = $this->getConnection(); + $select = $connection->select()->from( + $this->getMainTable(), + ['count' => new \Zend_Db_Expr('COUNT(*)')] + )->where( + 'product_id = :product_id' + ) ; + + return $connection->fetchOne( + $select, + [ + 'product_id' => $parentId + ] + ) > 0; + } + /** * Save Product Links process * diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Collection.php index 7f1c3fe0436b4..9cbdf2fbdf3c8 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Collection.php @@ -1,6 +1,6 @@ storeManager = $storeManager; + $this->resource = $resourceConnection; + $this->eavConfig = $eavConfig; + $this->catalogHelper = $catalogHelper; + $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); + } + + /** + * {@inheritdoc} + */ + public function build($productId) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $priceAttribute = $this->eavConfig->getAttribute(Product::ENTITY, 'price'); + $productTable = $this->resource->getTableName('catalog_product_entity'); + + $priceSelect = $this->resource->getConnection()->select() + ->from(['parent' => $productTable], '') + ->joinInner( + ['link' => $this->resource->getTableName('catalog_product_relation')], + "link.parent_id = parent.$linkField", + [] + )->joinInner( + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + ['entity_id'] + )->joinInner( + ['t' => $priceAttribute->getBackendTable()], + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + )->where('parent.entity_id = ?', $productId) + ->where('t.attribute_id = ?', $priceAttribute->getAttributeId()) + ->where('t.value IS NOT NULL') + ->order('t.value ' . Select::SQL_ASC) + ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); + + $priceSelectDefault = clone $priceSelect; + $priceSelectDefault->where('t.store_id = ?', Store::DEFAULT_STORE_ID); + $select[] = $priceSelectDefault; + + if (!$this->catalogHelper->isPriceGlobal()) { + $priceSelect->where('t.store_id = ?', $this->storeManager->getStore()->getId()); + $select[] = $priceSelect; + } + + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php new file mode 100644 index 0000000000000..e202a6846edaf --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php @@ -0,0 +1,156 @@ +storeManager = $storeManager; + $this->resource = $resourceConnection; + $this->eavConfig = $eavConfig; + $this->catalogHelper = $catalogHelper; + $this->dateTime = $dateTime; + $this->localeDate = $localeDate; + $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); + } + + /** + * {@inheritdoc} + */ + public function build($productId) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $connection = $this->resource->getConnection(); + $specialPriceAttribute = $this->eavConfig->getAttribute(Product::ENTITY, 'special_price'); + $specialPriceFromDate = $this->eavConfig->getAttribute(Product::ENTITY, 'special_from_date'); + $specialPriceToDate = $this->eavConfig->getAttribute(Product::ENTITY, 'special_to_date'); + $timestamp = $this->localeDate->scopeTimeStamp($this->storeManager->getStore()); + $currentDate = $this->dateTime->formatDate($timestamp, false); + $productTable = $this->resource->getTableName('catalog_product_entity'); + + $specialPrice = $this->resource->getConnection()->select() + ->from(['parent' => $productTable], '') + ->joinInner( + ['link' => $this->resource->getTableName('catalog_product_relation')], + "link.parent_id = parent.$linkField", + [] + )->joinInner( + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] + )->joinInner( + ['t' => $specialPriceAttribute->getBackendTable()], + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + )->joinLeft( + ['special_from' => $specialPriceFromDate->getBackendTable()], + $connection->quoteInto( + "t.{$linkField} = special_from.{$linkField} AND special_from.attribute_id = ?", + $specialPriceFromDate->getAttributeId() + ), + '' + )->joinLeft( + ['special_to' => $specialPriceToDate->getBackendTable()], + $connection->quoteInto( + "t.{$linkField} = special_to.{$linkField} AND special_to.attribute_id = ?", + $specialPriceToDate->getAttributeId() + ), + '' + )->where('parent.entity_id = ?', $productId) + ->where('t.attribute_id = ?', $specialPriceAttribute->getAttributeId()) + ->where('t.value IS NOT NULL') + ->where( + 'special_from.value IS NULL OR ' . $connection->getDatePartSql('special_from.value') .' <= ?', + $currentDate + )->where( + 'special_to.value IS NULL OR ' . $connection->getDatePartSql('special_to.value') .' >= ?', + $currentDate + )->order('t.value ' . Select::SQL_ASC) + ->limit(1); + $specialPrice = $this->baseSelectProcessor->process($specialPrice); + + $specialPriceDefault = clone $specialPrice; + $specialPriceDefault->where('t.store_id = ?', Store::DEFAULT_STORE_ID); + $select[] = $specialPriceDefault; + + if (!$this->catalogHelper->isPriceGlobal()) { + $specialPrice->where('t.store_id = ?', $this->storeManager->getStore()->getId()); + $select[] = $specialPrice; + } + + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php new file mode 100644 index 0000000000000..bd6f9ff198b2d --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php @@ -0,0 +1,114 @@ +storeManager = $storeManager; + $this->resource = $resourceConnection; + $this->customerSession = $customerSession; + $this->catalogHelper = $catalogHelper; + $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); + } + + /** + * {@inheritdoc} + */ + public function build($productId) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $productTable = $this->resource->getTableName('catalog_product_entity'); + + $priceSelect = $this->resource->getConnection()->select() + ->from(['parent' => $productTable], '') + ->joinInner( + ['link' => $this->resource->getTableName('catalog_product_relation')], + "link.parent_id = parent.$linkField", + [] + )->joinInner( + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] + )->joinInner( + ['t' => $this->resource->getTableName('catalog_product_entity_tier_price')], + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + )->where('parent.entity_id = ?', $productId) + ->where('t.all_groups = 1 OR customer_group_id = ?', $this->customerSession->getCustomerGroupId()) + ->where('t.qty = ?', 1) + ->order('t.value ' . Select::SQL_ASC) + ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); + + $priceSelectDefault = clone $priceSelect; + $priceSelectDefault->where('t.website_id = ?', self::DEFAULT_WEBSITE_ID); + $select[] = $priceSelectDefault; + + if (!$this->catalogHelper->isPriceGlobal()) { + $priceSelect->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()); + $select[] = $priceSelect; + } + + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderComposite.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderComposite.php new file mode 100644 index 0000000000000..377a4d6429e54 --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderComposite.php @@ -0,0 +1,36 @@ +linkedProductSelectBuilder = $linkedProductSelectBuilder; + } + + /** + * {@inheritdoc} + */ + public function build($productId) + { + $select = []; + foreach ($this->linkedProductSelectBuilder as $productSelectBuilder) { + $select = array_merge($select, $productSelectBuilder->build($productId)); + } + + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderInterface.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderInterface.php new file mode 100644 index 0000000000000..94bdaeaedf552 --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderInterface.php @@ -0,0 +1,18 @@ +eavConfig = $eavConfig; + $this->metadataPool = $metadataPool; + $this->storeResolver = $storeResolver; + } + + /** + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $statusAttribute = $this->eavConfig->getAttribute(Product::ENTITY, ProductInterface::STATUS); + + $select->joinLeft( + ['status_global_attr' => $statusAttribute->getBackendTable()], + "status_global_attr.{$linkField} = " . self::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . ' AND status_global_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId() + . ' AND status_global_attr.store_id = ' . Store::DEFAULT_STORE_ID, + [] + ); + + $select->joinLeft( + ['status_attr' => $statusAttribute->getBackendTable()], + "status_attr.{$linkField} = " . self::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . ' AND status_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId() + . ' AND status_attr.store_id = ' . $this->storeResolver->getCurrentStoreId(), + [] + ); + + $select->where('IFNULL(status_attr.value, status_global_attr.value) = ?', Status::STATUS_ENABLED); + + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Website.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Website.php index 69d58ddefb700..b355c9e6374bb 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Website.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Website.php @@ -1,6 +1,6 @@ config = $config; + $this->productAttributeRepository = $productAttributeRepository; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + } + + /** + * Change scope for all price attributes according to + * 'Catalog Price Scope' configuration parameter value + * + * @param EventObserver $observer + * @return void + */ + public function execute(EventObserver $observer) + { + $this->searchCriteriaBuilder->addFilter('frontend_input', 'price'); + $criteria = $this->searchCriteriaBuilder->create(); + + $scope = $this->config->getValue(Store::XML_PATH_PRICE_SCOPE); + $scope = ($scope == Store::PRICE_SCOPE_WEBSITE) + ? ProductAttributeInterface::SCOPE_WEBSITE_TEXT + : ProductAttributeInterface::SCOPE_GLOBAL_TEXT; + + $priceAttributes = $this->productAttributeRepository->getList($criteria)->getItems(); + + /** @var ProductAttributeInterface $priceAttribute */ + foreach ($priceAttributes as $priceAttribute) { + $priceAttribute->setScope($scope); + $this->productAttributeRepository->save($priceAttribute); + } + } +} diff --git a/app/code/Magento/Catalog/Plugin/Block/Topmenu.php b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php index 098b3282a1b10..8a4d8efd8a744 100644 --- a/app/code/Magento/Catalog/Plugin/Block/Topmenu.php +++ b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php @@ -1,6 +1,6 @@ maximalPrice) { - $this->maximalPrice = $this->calculator->getAmount($this->getValue(), $this->product); + $maximalPrice = $this->product->getMaximalPrice(); + if ($maximalPrice === null) { + $maximalPrice = $this->getValue(); + } else { + $maximalPrice = $this->priceCurrency->convertAndRound($maximalPrice); + } + $this->maximalPrice = $this->calculator->getAmount($maximalPrice, $this->product); } return $this->maximalPrice; } diff --git a/app/code/Magento/Catalog/Pricing/Price/FinalPriceInterface.php b/app/code/Magento/Catalog/Pricing/Price/FinalPriceInterface.php index b0a5d5468017e..c804ba8649cfb 100644 --- a/app/code/Magento/Catalog/Pricing/Price/FinalPriceInterface.php +++ b/app/code/Magento/Catalog/Pricing/Price/FinalPriceInterface.php @@ -1,6 +1,6 @@ salableResolver = $salableResolver ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(SalableResolverInterface::class); + } + /** * @return string */ protected function _toHtml() { - if (!$this->getSaleableItem() || $this->getSaleableItem()->getCanShowPrice() === false) { + // Check catalog permissions + if ($this->getSaleableItem()->getCanShowPrice() === false) { return ''; } $result = parent::_toHtml(); - try { - /** @var MsrpPrice $msrpPriceType */ - $msrpPriceType = $this->getSaleableItem()->getPriceInfo()->getPrice('msrp_price'); - } catch (\InvalidArgumentException $e) { - $this->_logger->critical($e); - return $this->wrapResult($result); - } - //Renders MSRP in case it is enabled - $product = $this->getSaleableItem(); - if ($msrpPriceType->canApplyMsrp($product) && $msrpPriceType->isMinimalPriceLessMsrp($product)) { + if ($this->isMsrpPriceApplicable()) { /** @var BasePriceBox $msrpBlock */ $msrpBlock = $this->rendererPool->createPriceRender( MsrpPrice::PRICE_CODE, @@ -56,6 +85,36 @@ protected function _toHtml() return $this->wrapResult($result); } + /** + * Check is MSRP applicable for the current product. + * + * @return bool + */ + private function isMsrpPriceApplicable() + { + $moduleManager = $this->getModuleManager(); + + if (!$moduleManager->isEnabled('Magento_Msrp') || !$moduleManager->isOutputEnabled('Magento_Msrp')) { + return false; + } + + try { + /** @var MsrpPrice $msrpPriceType */ + $msrpPriceType = $this->getSaleableItem()->getPriceInfo()->getPrice('msrp_price'); + } catch (\InvalidArgumentException $e) { + $this->_logger->critical($e); + return false; + } + + if ($msrpPriceType === null) { + return false; + } + + $product = $this->getSaleableItem(); + + return $msrpPriceType->canApplyMsrp($product) && $msrpPriceType->isMinimalPriceLessMsrp($product); + } + /** * Wrap with standard required container * @@ -118,4 +177,51 @@ public function showMinimalPrice() && $minimalPriceAValue && $minimalPriceAValue < $finalPriceValue; } + + /** + * Get Key for caching block content + * + * @return string + */ + public function getCacheKey() + { + return parent::getCacheKey() . ($this->getData('list_category_page') ? '-list-category-page': ''); + } + + /** + * {@inheritdoc} + * + * @return array + */ + public function getCacheKeyInfo() + { + $cacheKeys = parent::getCacheKeyInfo(); + $cacheKeys['display_minimal_price'] = $this->getDisplayMinimalPrice(); + $cacheKeys['is_product_list'] = $this->isProductList(); + return $cacheKeys; + } + + /** + * @deprecated + * @return Manager + */ + private function getModuleManager() + { + if ($this->moduleManager === null) { + $this->moduleManager = ObjectManager::getInstance()->get(Manager::class); + } + return $this->moduleManager; + } + + /** + * Get flag that price rendering should be done for the list of products + * By default (if flag is not set) is false + * + * @return bool + */ + public function isProductList() + { + $isProductList = $this->getData('is_product_list'); + return $isProductList === true; + } } diff --git a/app/code/Magento/Catalog/Pricing/Render/PriceBox.php b/app/code/Magento/Catalog/Pricing/Render/PriceBox.php index 92ff22decb1d0..156fbb8633699 100644 --- a/app/code/Magento/Catalog/Pricing/Render/PriceBox.php +++ b/app/code/Magento/Catalog/Pricing/Render/PriceBox.php @@ -1,6 +1,6 @@ [ + 'entity_type_id' => 3, 'entity_model' => 'Magento\Catalog\Model\ResourceModel\Category', 'attribute_model' => 'Magento\Catalog\Model\ResourceModel\Eav\Attribute', 'table' => 'catalog_category_entity', @@ -334,6 +335,7 @@ public function getDefaultEntities() ], ], 'catalog_product' => [ + 'entity_type_id' => 4, 'entity_model' => 'Magento\Catalog\Model\ResourceModel\Product', 'attribute_model' => 'Magento\Catalog\Model\ResourceModel\Eav\Attribute', 'table' => 'catalog_product_entity', diff --git a/app/code/Magento/Catalog/Setup/InstallData.php b/app/code/Magento/Catalog/Setup/InstallData.php index baad2c756daf8..b9e4468db83e2 100644 --- a/app/code/Magento/Catalog/Setup/InstallData.php +++ b/app/code/Magento/Catalog/Setup/InstallData.php @@ -1,6 +1,6 @@ getVersion(), '2.0.7') < 0) { - /** @var EavSetup $eavSetupF */ + /** @var EavSetup $eavSetup */ $eavSetup= $this->eavSetupFactory->create(['setup' => $setup]); $eavSetup->updateAttribute( @@ -351,7 +351,32 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface ] ); } - + + if (version_compare($context->getVersion(), '2.1.3') < 0) { + /** @var \Magento\Catalog\Setup\CategorySetup $categorySetup */ + $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]); + $this->changePriceAttributeDefaultScope($categorySetup); + } + $setup->endSetup(); } + + /** + * @param \Magento\Catalog\Setup\CategorySetup $categorySetup + * @return void + */ + private function changePriceAttributeDefaultScope($categorySetup) + { + $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY); + foreach (['price', 'cost', 'special_price'] as $attributeCode) { + $attribute = $categorySetup->getAttribute($entityTypeId, $attributeCode); + $categorySetup->updateAttribute( + $entityTypeId, + $attribute['attribute_id'], + 'is_global', + \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL + ); + + } + } } diff --git a/app/code/Magento/Catalog/Setup/UpgradeSchema.php b/app/code/Magento/Catalog/Setup/UpgradeSchema.php index 03f3ac9581729..aef2501aa9aaa 100644 --- a/app/code/Magento/Catalog/Setup/UpgradeSchema.php +++ b/app/code/Magento/Catalog/Setup/UpgradeSchema.php @@ -1,6 +1,6 @@ fileSystemMock = $this->getMock('Magento\Framework\Filesystem', [], [], '', false); + $this->fileSystemMock = $this->getMock( + 'Magento\Framework\Filesystem', + ['stat', 'getDirectoryRead'], + [], + '', + false + ); $this->readMock = $this->getMock('Magento\Framework\Filesystem\Directory\ReadInterface'); $this->galleryMock = $this->getMock( 'Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery', @@ -56,7 +68,13 @@ public function setUp() '', false ); - $this->mediaConfigMock = $this->getMock('Magento\Catalog\Model\Product\Media\Config', [], [], '', false); + $this->mediaConfigMock = $this->getMock( + 'Magento\Catalog\Model\Product\Media\Config', + ['getMediaUrl', 'getMediaPath'], + [], + '', + false + ); $this->jsonEncoderMock = $this->getMockBuilder('Magento\Framework\Json\EncoderInterface') ->disableOriginalConstructor() ->getMock(); @@ -130,7 +148,6 @@ public function testGetImagesJson() $this->mediaConfigMock->expects($this->any())->method('getMediaUrl')->willReturnMap($url); $this->mediaConfigMock->expects($this->any())->method('getMediaPath')->willReturnMap($mediaPath); - $this->readMock->expects($this->any())->method('stat')->willReturnMap($sizeMap); $this->jsonEncoderMock->expects($this->once())->method('encode')->willReturnCallback('json_encode'); @@ -144,4 +161,74 @@ public function testGetImagesJsonWithoutImages() $this->assertSame('[]', $this->content->getImagesJson()); } + + public function testGetImagesJsonWithException() + { + $this->imageHelper = $this->getMockBuilder('Magento\Catalog\Helper\Image') + ->disableOriginalConstructor() + ->setMethods(['getDefaultPlaceholderUrl']) + ->getMock(); + + $this->objectManager->setBackwardCompatibleProperty( + $this->content, + 'imageHelper', + $this->imageHelper + ); + + $placeholderUrl = 'url_to_the_placeholder/placeholder.jpg'; + + $imagesResult = [ + [ + 'value_id' => '2', + 'file' => 'file_2.jpg', + 'media_type' => 'image', + 'position' => '0', + 'url' => 'url_to_the_placeholder/placeholder.jpg', + 'size' => 0 + ], + [ + 'value_id' => '1', + 'file' => 'file_1.jpg', + 'media_type' => 'image', + 'position' => '1', + 'url' => 'url_to_the_placeholder/placeholder.jpg', + 'size' => 0 + ] + ]; + + $images = [ + 'images' => [ + [ + 'value_id' => '1', + 'file' => 'file_1.jpg', + 'media_type' => 'image', + 'position' => '1' + ], + [ + 'value_id' => '2', + 'file' => 'file_2.jpg', + 'media_type' => 'image', + 'position' => '0' + ] + ] + ]; + + $this->content->setElement($this->galleryMock); + $this->galleryMock->expects($this->once())->method('getImages')->willReturn($images); + $this->fileSystemMock->expects($this->any())->method('getDirectoryRead')->willReturn($this->readMock); + $this->mediaConfigMock->expects($this->any())->method('getMediaUrl'); + $this->mediaConfigMock->expects($this->any())->method('getMediaPath'); + $this->readMock->expects($this->any())->method('stat')->willReturnOnConsecutiveCalls( + $this->throwException( + new \Magento\Framework\Exception\FileSystemException(new Phrase('test')) + ), + $this->throwException( + new \Magento\Framework\Exception\FileSystemException(new Phrase('test')) + ) + ); + $this->imageHelper->expects($this->any())->method('getDefaultPlaceholderUrl')->willReturn($placeholderUrl); + $this->jsonEncoderMock->expects($this->once())->method('encode')->willReturnCallback('json_encode'); + + $this->assertSame(json_encode($imagesResult), $this->content->getImagesJson()); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/GalleryTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/GalleryTest.php index 044b2470d9366..4836e9fedb497 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/GalleryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/GalleryTest.php @@ -1,6 +1,6 @@ registryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false); - $this->layerMock = $this->getMock('Magento\Catalog\Model\Layer', [], [], '', false); + $this->registryMock = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); + $this->layerMock = $this->getMock(\Magento\Catalog\Model\Layer::class, [], [], '', false); /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Layer\Resolver $layerResolver */ - $layerResolver = $this->getMockBuilder('\Magento\Catalog\Model\Layer\Resolver') + $layerResolver = $this->getMockBuilder(\Magento\Catalog\Model\Layer\Resolver::class) ->disableOriginalConstructor() ->setMethods(['get', 'create']) ->getMock(); @@ -61,14 +85,14 @@ protected function setUp() ->method($this->anything()) ->will($this->returnValue($this->layerMock)); $this->postDataHelperMock = $this->getMock( - 'Magento\Framework\Data\Helper\PostHelper', + \Magento\Framework\Data\Helper\PostHelper::class, [], [], '', false ); $this->typeInstanceMock = $this->getMock( - 'Magento\Catalog\Model\Product\Type\Simple', + \Magento\Catalog\Model\Product\Type\Simple::class, [], [], '', @@ -76,28 +100,48 @@ protected function setUp() false ); $this->productMock = $this->getMock( - 'Magento\Catalog\Model\Product', + \Magento\Catalog\Model\Product::class, [], [], '', false ); $this->cartHelperMock = $this->getMock( - 'Magento\Checkout\Helper\Cart', + \Magento\Checkout\Helper\Cart::class, [], [], '', false ); - $this->urlHelperMock = $this->getMockBuilder('Magento\Framework\Url\Helper\Data') + $this->urlHelperMock = $this->getMockBuilder(\Magento\Framework\Url\Helper\Data::class) ->disableOriginalConstructor()->getMock(); + + $this->layout = $this->getMockBuilder(LayoutInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->context = $this->getMockBuilder(Context::class) + ->disableOriginalConstructor() + ->getMock(); + $this->renderer = $this->getMockBuilder(Render::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->context->expects($this->any()) + ->method('getRegistry') + ->willReturn($this->registryMock); + $this->context->expects($this->any()) + ->method('getCartHelper') + ->willReturn($this->cartHelperMock); + $this->context->expects($this->any()) + ->method('getLayout') + ->willReturn($this->layout); + $this->block = $objectManager->getObject( - 'Magento\Catalog\Block\Product\ListProduct', + \Magento\Catalog\Block\Product\ListProduct::class, [ - 'registry' => $this->registryMock, + 'context' => $this->context, 'layerResolver' => $layerResolver, - 'cartHelper' => $this->cartHelperMock, 'postDataHelper' => $this->postDataHelperMock, 'urlHelper' => $this->urlHelperMock, ] @@ -118,11 +162,14 @@ public function testGetIdentities() ->method('getIdentities') ->will($this->returnValue([$productTag])); - $itemsCollection = new \ReflectionProperty('Magento\Catalog\Block\Product\ListProduct', '_productCollection'); + $itemsCollection = new \ReflectionProperty( + \Magento\Catalog\Block\Product\ListProduct::class, + '_productCollection' + ); $itemsCollection->setAccessible(true); $itemsCollection->setValue($this->block, [$this->productMock]); - $currentCategory = $this->getMock('Magento\Catalog\Model\Category', [], [], '', false); + $currentCategory = $this->getMock(\Magento\Catalog\Model\Category::class, [], [], '', false); $currentCategory->expects($this->once()) ->method('getId') ->will($this->returnValue('1')); @@ -168,4 +215,18 @@ public function testGetAddToCartPostParams() $result = $this->block->getAddToCartPostParams($this->productMock); $this->assertEquals($expectedPostData, $result); } + + public function testSetIsProductListFlagOnGetProductPrice() + { + $this->renderer->expects($this->once()) + ->method('setData') + ->with('is_product_list', true) + ->willReturnSelf(); + $this->layout->expects($this->once()) + ->method('getBlock') + ->with('product.price.render.default') + ->willReturn($this->renderer); + + $this->block->getProductPrice($this->productMock); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ListTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ListTest.php index d3cfccdfb3fe2..b97064eed8828 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ListTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ListTest.php @@ -1,6 +1,6 @@ objectManager->getObject(Validate::class, [ - 'context' => $this->contextMock, - 'attributeLabelCache' => $this->attributeLabelCacheMock, - 'coreRegistry' => $this->coreRegistryMock, - 'resultPageFactory' => $this->resultPageFactoryMock, - 'resultJsonFactory' => $this->resultJsonFactoryMock, - 'layoutFactory' => $this->layoutFactoryMock, - ]); + return $this->objectManager->getObject( + Validate::class, + [ + 'context' => $this->contextMock, + 'attributeLabelCache' => $this->attributeLabelCacheMock, + 'coreRegistry' => $this->coreRegistryMock, + 'resultPageFactory' => $this->resultPageFactoryMock, + 'resultJsonFactory' => $this->resultJsonFactoryMock, + 'layoutFactory' => $this->layoutFactoryMock, + 'multipleAttributeList' => ['select' => 'option'] + ] + ); } public function testExecute() @@ -119,8 +123,8 @@ public function testExecute() $this->objectManagerMock->expects($this->exactly(2)) ->method('create') ->willReturnMap([ - ['Magento\Catalog\Model\ResourceModel\Eav\Attribute', [], $this->attributeMock], - ['Magento\Eav\Model\Entity\Attribute\Set', [], $this->attributeSetMock] + [\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, [], $this->attributeMock], + [\Magento\Eav\Model\Entity\Attribute\Set::class, [], $this->attributeSetMock] ]); $this->attributeMock->expects($this->once()) ->method('loadByCode') @@ -147,4 +151,98 @@ public function testExecute() $this->assertInstanceOf(ResultJson::class, $this->getModel()->execute()); } + + /** + * @dataProvider provideUniqueData + * @param array $options + * @param boolean $isError + * @throws \Magento\Framework\Exception\NotFoundException + */ + public function testUniqueValidation(array $options, $isError) + { + $countFunctionCalls = ($isError) ? 6 : 5; + $this->requestMock->expects($this->exactly($countFunctionCalls)) + ->method('getParam') + ->willReturnMap([ + ['frontend_label', null, null], + ['attribute_code', null, 'test_attribute_code'], + ['new_attribute_set_name', null, 'test_attribute_set_name'], + ['option', null, $options], + ['message_key', null, Validate::DEFAULT_MESSAGE_KEY] + ]); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->willReturn($this->attributeMock); + + $this->attributeMock->expects($this->once()) + ->method('loadByCode') + ->willReturnSelf(); + + $this->requestMock->expects($this->once()) + ->method('has') + ->with('new_attribute_set_name') + ->willReturn(false); + + $this->resultJsonFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->resultJson); + + $this->resultJson->expects($this->once()) + ->method('setJsonData') + ->willReturnSelf(); + + $this->assertInstanceOf(ResultJson::class, $this->getModel()->execute()); + } + + public function provideUniqueData() + { + return [ + // valid options + [ + [ + 'value' => [ + "option_0" => [1, 0], + "option_1" => [2, 0], + "option_2" => [3, 0], + ], + 'delete' => [ + "option_0" => "", + "option_1" => "", + "option_2" => "", + ] + ], false + ], + //with duplicate + [ + [ + 'value' => [ + "option_0" => [1, 0], + "option_1" => [1, 0], + "option_2" => [3, 0], + ], + 'delete' => [ + "option_0" => "", + "option_1" => "", + "option_2" => "", + ] + ], true + ], + //with duplicate but deleted + [ + [ + 'value' => [ + "option_0" => [1, 0], + "option_1" => [1, 0], + "option_2" => [3, 0], + ], + 'delete' => [ + "option_0" => "", + "option_1" => "1", + "option_2" => "", + ] + ], false + ], + ]; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php index e64b8e06a2f8e..2dd1a0ab3b64a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php @@ -1,6 +1,6 @@ objectManager = new ObjectManager($this); $this->productLinkFactoryMock = $this->getMockBuilder(ProductLinkInterfaceFactory::class) + ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); $this->productRepositoryMock = $this->getMockBuilder(ProductRepository::class) @@ -150,7 +159,6 @@ protected function setUp() '__sleep', '__wakeup', 'getSku', - 'getProductLinks', 'getWebsiteIds' ]) ->disableOriginalConstructor() @@ -165,10 +173,12 @@ protected function setUp() $this->productLinksMock = $this->getMockBuilder(ProductLinks::class) ->disableOriginalConstructor() ->getMock(); - $this->productLinksMock->expects($this->any()) ->method('initializeLinks') ->willReturn($this->productMock); + $this->linkTypeProviderMock = $this->getMockBuilder(LinkTypeProvider::class) + ->disableOriginalConstructor() + ->getMock(); $this->helper = $this->objectManager->getObject(Helper::class, [ 'request' => $this->requestMock, @@ -179,6 +189,7 @@ protected function setUp() 'customOptionFactory' => $this->customOptionFactoryMock, 'productLinkFactory' => $this->productLinkFactoryMock, 'productRepository' => $this->productRepositoryMock, + 'linkTypeProvider' => $this->linkTypeProviderMock, ]); $this->linkResolverMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Link\Resolver::class) @@ -191,10 +202,10 @@ protected function setUp() } /** - * @covers \Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper::initialize * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @param array $links */ - public function testInitialize() + private function assembleProductMock($links = []) { $this->customOptionMock->expects($this->once()) ->method('setProductSku'); @@ -230,9 +241,6 @@ public function testInitialize() $attributeDate->expects($this->any()) ->method('getBackend') ->willReturn($attributeDateBackEnd); - $this->productMock->expects($this->any()) - ->method('getProductLinks') - ->willReturn([]); $attributeNonDateBackEnd->expects($this->any()) ->method('getType') ->willReturn('non-datetime'); @@ -255,7 +263,7 @@ public function testInitialize() ->method('getPost') ->with('use_default') ->willReturn($useDefaults); - $this->linkResolverMock->expects($this->once())->method('getLinks')->willReturn([]); + $this->linkResolverMock->expects($this->once())->method('getLinks')->willReturn($links); $this->stockFilterMock->expects($this->once()) ->method('filter') ->with(['stock_data']) @@ -267,9 +275,6 @@ public function testInitialize() $this->productMock->expects($this->once()) ->method('unlockAttribute') ->with('media'); - $this->productMock->expects($this->any()) - ->method('getProductLinks') - ->willReturn([]); $this->productMock->expects($this->once()) ->method('lockAttribute') ->with('media'); @@ -284,7 +289,7 @@ public function testInitialize() $this->productMock->expects($this->once()) ->method('addData') ->with($productData); - $this->productMock->expects($this->once()) + $this->productMock->expects($this->any()) ->method('getSku') ->willReturn('sku'); $this->productMock->expects($this->any()) @@ -298,10 +303,193 @@ public function testInitialize() $this->productMock->expects($this->once()) ->method('setOptions') ->with([$this->customOptionMock]); + } + + /** + * @covers \Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper::initialize + */ + public function testInitialize() + { + $this->assembleProductMock(); + $this->linkTypeProviderMock->expects($this->once()) + ->method('getItems') + ->willReturn($this->assembleLinkTypes(['related', 'upsell', 'crosssell'])); $this->assertEquals($this->productMock, $this->helper->initialize($this->productMock)); } + /** + * @covers \Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper::initialize + * @dataProvider initializeWithLinksDataProvider + */ + public function testInitializeWithLinks($links, $linkTypes, $expectedLinks) + { + $this->productLinkFactoryMock->expects($this->any()) + ->method('create') + ->willReturnCallback(function () { + return $this->getMockBuilder(ProductLink::class) + ->setMethods(null) + ->disableOriginalConstructor() + ->getMock(); + }); + + $this->linkTypeProviderMock->expects($this->once()) + ->method('getItems') + ->willReturn($this->assembleLinkTypes($linkTypes)); + + $this->assembleProductRepositoryMock($links); + $this->assembleProductMock($links); + + $this->assertEquals($this->productMock, $this->helper->initialize($this->productMock)); + + $productLinks = $this->productMock->getProductLinks(); + $this->assertCount(count($expectedLinks), $productLinks); + $resultLinks = []; + + foreach ($productLinks as $link) { + $this->assertInstanceOf(ProductLink::class, $link); + $this->assertEquals('sku', $link->getSku()); + $resultLinks[] = ['type' => $link->getLinkType(), 'linked_product_sku' => $link->getLinkedProductSku()]; + } + + $this->assertEquals($expectedLinks, $resultLinks); + } + + /** + * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function initializeWithLinksDataProvider() + { + return [ + // No links + [ + 'links' => [], + 'linkTypes' => ['related', 'upsell', 'crosssell'], + 'expected_links' => [], + ], + + // Related links + [ + 'links' => [ + 'related' => [ + 0 => [ + 'id' => 1, + 'thumbnail' => 'http://magento.dev/media/no-image.jpg', + 'name' => 'Test', + 'status' => 'Enabled', + 'attribute_set' => 'Default', + 'sku' => 'Test', + 'price' => 1.00, + 'position' => 1, + 'record_id' => 1, + ] + ] + ], + 'linkTypes' => ['related', 'upsell', 'crosssell'], + 'expected_links' => [ + ['type' => 'related', 'linked_product_sku' => 'Test'], + ], + ], + + // Custom link + [ + 'links' => [ + 'customlink' => [ + 0 => [ + 'id' => 4, + 'thumbnail' => 'http://magento.dev/media/no-image.jpg', + 'name' => 'Test Custom', + 'status' => 'Enabled', + 'attribute_set' => 'Default', + 'sku' => 'Testcustom', + 'price' => 1.00, + 'position' => 1, + 'record_id' => 1, + ], + ], + ], + 'linkTypes' => ['related', 'upsell', 'crosssell', 'customlink'], + 'expected_links' => [ + ['type' => 'customlink', 'linked_product_sku' => 'Testcustom'], + ], + ], + + // Both links + [ + 'links' => [ + 'related' => [ + 0 => [ + 'id' => 1, + 'thumbnail' => 'http://magento.dev/media/no-image.jpg', + 'name' => 'Test', + 'status' => 'Enabled', + 'attribute_set' => 'Default', + 'sku' => 'Test', + 'price' => 1.00, + 'position' => 1, + 'record_id' => 1, + ], + ], + 'customlink' => [ + 0 => [ + 'id' => 4, + 'thumbnail' => 'http://magento.dev/media/no-image.jpg', + 'name' => 'Test Custom', + 'status' => 'Enabled', + 'attribute_set' => 'Default', + 'sku' => 'Testcustom', + 'price' => 2.00, + 'position' => 2, + 'record_id' => 1, + ], + ], + ], + 'linkTypes' => ['related', 'upsell', 'crosssell', 'customlink'], + 'expected_links' => [ + ['type' => 'related', 'linked_product_sku' => 'Test'], + ['type' => 'customlink', 'linked_product_sku' => 'Testcustom'], + ], + ], + + // Undefined link type + [ + 'links' => [ + 'related' => [ + 0 => [ + 'id' => 1, + 'thumbnail' => 'http://magento.dev/media/no-image.jpg', + 'name' => 'Test', + 'status' => 'Enabled', + 'attribute_set' => 'Default', + 'sku' => 'Test', + 'price' => 1.00, + 'position' => 1, + 'record_id' => 1, + ], + ], + 'customlink' => [ + 0 => [ + 'id' => 4, + 'thumbnail' => 'http://magento.dev/media/no-image.jpg', + 'name' => 'Test Custom', + 'status' => 'Enabled', + 'attribute_set' => 'Default', + 'sku' => 'Testcustom', + 'price' => 2.00, + 'position' => 2, + 'record_id' => 1, + ], + ], + ], + 'linkTypes' => ['related', 'upsell', 'crosssell'], + 'expected_links' => [ + ['type' => 'related', 'linked_product_sku' => 'Test'], + ], + ], + ]; + } + /** * Data provider for testMergeProductOptions * @@ -391,4 +579,55 @@ public function testMergeProductOptions($productOptions, $defaultOptions, $expec $result = $this->helper->mergeProductOptions($productOptions, $defaultOptions); $this->assertEquals($expectedResults, $result); } + + /** + * @param array $types + * @return array + */ + private function assembleLinkTypes($types) + { + $linkTypes = []; + $linkTypeCode = 1; + + foreach ($types as $typeName) { + $linkType = $this->getMock(ProductLinkTypeInterface::class); + $linkType->method('getCode')->willReturn($linkTypeCode++); + $linkType->method('getName')->willReturn($typeName); + + $linkTypes[] = $linkType; + } + + return $linkTypes; + } + + /** + * @param array $links + */ + private function assembleProductRepositoryMock($links) + { + $repositoryReturnMap = []; + + foreach ($links as $linkType) { + foreach ($linkType as $link) { + $mockLinkedProduct = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockLinkedProduct->expects($this->any()) + ->method('getId') + ->willReturn($link['id']); + + $mockLinkedProduct->expects($this->any()) + ->method('getSku') + ->willReturn($link['sku']); + + // Even optional arguments need to be provided for returnMapValue + $repositoryReturnMap[] = [$link['id'], false, null, false, $mockLinkedProduct]; + } + } + + $this->productRepositoryMock->expects($this->any()) + ->method('getById') + ->will($this->returnValueMap($repositoryReturnMap)); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/StockDataFilterTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/StockDataFilterTest.php index 9cd056c997b64..e73269ac8f576 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/StockDataFilterTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/StockDataFilterTest.php @@ -1,6 +1,6 @@ priceProcessor = $this->getMockBuilder('Magento\Catalog\Model\Indexer\Product\Price\Processor') + $objectManagerMock = $this->getMockBuilder(Manager::class) + ->disableOriginalConstructor() + ->getMock(); + + $objectManagerHelper = new ObjectManager($this); + $this->priceProcessorMock = $this->getMockBuilder(Processor::class) ->disableOriginalConstructor()->getMock(); - $productBuilder = $this->getMockBuilder('Magento\Catalog\Controller\Adminhtml\Product\Builder')->setMethods([ + $productBuilderMock = $this->getMockBuilder(Builder::class)->setMethods([ 'build', ])->disableOriginalConstructor()->getMock(); - $product = $this->getMockBuilder('\Magento\Catalog\Model\Product')->disableOriginalConstructor() + $this->requestMock = $this->getMockBuilder(Http::class)->setMethods( + ['getParam', 'getPost', 'getFullActionName', 'getPostValue'] + )->disableOriginalConstructor()->getMock(); + + $productMock = $this->getMockBuilder(Product::class)->disableOriginalConstructor() ->setMethods(['getTypeId', 'getStoreId', '__sleep', '__wakeup'])->getMock(); - $product->expects($this->any())->method('getTypeId')->will($this->returnValue('simple')); - $product->expects($this->any())->method('getStoreId')->will($this->returnValue('1')); - $productBuilder->expects($this->any())->method('build')->will($this->returnValue($product)); + $productMock->expects($this->any())->method('getTypeId')->will($this->returnValue('simple')); + $productMock->expects($this->any())->method('getStoreId')->will($this->returnValue('1')); + $productBuilderMock->expects($this->any())->method('build')->will($this->returnValue($productMock)); - $this->resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') + $resultRedirectMock = $this->getMockBuilder(Redirect::class) ->disableOriginalConstructor() ->getMock(); - $resultFactory = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + $resultFactory = $this->getMockBuilder(ResultFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); $resultFactory->expects($this->atLeastOnce()) ->method('create') - ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT) - ->willReturn($this->resultRedirect); + ->with(ResultFactory::TYPE_REDIRECT) + ->willReturn($resultRedirectMock); - $abstractDbMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + $this->abstractDbMock = $this->getMockBuilder(AbstractDb::class) ->disableOriginalConstructor() ->setMethods(['getAllIds', 'getResource']) ->getMock(); - $abstractDbMock->expects($this->any()) + $this->abstractDbMock->expects($this->any()) ->method('getAllIds') ->willReturn([]); - $filterMock = $this->getMockBuilder('Magento\Ui\Component\MassAction\Filter') + $this->filterMock = $this->getMockBuilder(Filter::class) ->disableOriginalConstructor() ->setMethods(['getCollection']) ->getMock(); - $filterMock->expects($this->any()) + $this->filterMock->expects($this->any()) ->method('getCollection') - ->willReturn($abstractDbMock); - - $collectionFactoryMock = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\CollectionFactory') + ->willReturn($this->abstractDbMock); + $this->actionMock = $this->getMockBuilder(Action::class) + ->disableOriginalConstructor() + ->getMock(); + $objectManagerMock->expects($this->any())->method('get')->willReturn($this->actionMock); + $collectionFactoryMock = $this->getMockBuilder(CollectionFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); $collectionFactoryMock->expects($this->any()) ->method('create') - ->willReturn($abstractDbMock); - - $additionalParams = ['resultFactory' => $resultFactory]; - $this->action = new \Magento\Catalog\Controller\Adminhtml\Product\MassStatus( - $this->initContext($additionalParams), - $productBuilder, - $this->priceProcessor, - $filterMock, - $collectionFactoryMock + ->willReturn($this->abstractDbMock); + $this->requestMock = $this->getMockBuilder(Http::class)->setMethods( + ['getParam', 'getPost', 'getFullActionName', 'getPostValue'] + )->disableOriginalConstructor()->getMock(); + + $this->action = $objectManagerHelper->getObject( + MassStatus::class, + [ + 'objectManager' => $objectManagerMock, + 'request' => $this->requestMock, + 'productBuilder' => $productBuilderMock, + 'filter' => $this->filterMock, + 'productPriceIndexerProcessor' => $this->priceProcessorMock, + 'collectionFactory' => $collectionFactoryMock, + 'resultFactory' => $resultFactory + ] ); + } public function testMassStatusAction() { - $this->priceProcessor->expects($this->once())->method('reindexList'); + $storeId = 1; + $status = Status::STATUS_DISABLED; + $filters = [ + 'store_id' => 2, + ]; + + $productIds = [3]; + + $this->filterMock->expects($this->once()) + ->method('getCollection') + ->willReturn($this->abstractDbMock); + $this->abstractDbMock->expects($this->once()) + ->method('getAllIds') + ->willReturn($productIds); + $this->requestMock->expects($this->exactly(3)) + ->method('getParam') + ->willReturnMap([ + ['store', 0, $storeId], + ['status', null, $status], + ['filters', [], $filters] + ]); + $this->actionMock->expects($this->once()) + ->method('updateAttributes'); + $this->priceProcessorMock->expects($this->once()) + ->method('reindexList'); + $this->action->execute(); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/NewActionTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/NewActionTest.php index 34c39d6ad85cc..3c4dca76bfa84 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/NewActionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/NewActionTest.php @@ -1,13 +1,12 @@ productBuilder = $this->getMock( - 'Magento\Catalog\Controller\Adminhtml\Product\Builder', + \Magento\Catalog\Controller\Adminhtml\Product\Builder::class, ['build'], [], '', false ); - $this->product = $this->getMockBuilder('Magento\Catalog\Model\Product')->disableOriginalConstructor() + $this->product = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)->disableOriginalConstructor() ->setMethods(['addData', 'getTypeId', 'getStoreId', '__sleep', '__wakeup'])->getMock(); $this->product->expects($this->any())->method('getTypeId')->will($this->returnValue('simple')); $this->product->expects($this->any())->method('getStoreId')->will($this->returnValue('1')); $this->productBuilder->expects($this->any())->method('build')->will($this->returnValue($this->product)); - $this->resultPage = $this->getMockBuilder('Magento\Backend\Model\View\Result\Page') + $this->resultPage = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Page::class) ->disableOriginalConstructor() ->getMock(); - $resultPageFactory = $this->getMockBuilder('Magento\Framework\View\Result\PageFactory') + $resultPageFactory = $this->getMockBuilder(\Magento\Framework\View\Result\PageFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); @@ -60,10 +59,10 @@ protected function setUp() ->method('create') ->willReturn($this->resultPage); - $this->resultForward = $this->getMockBuilder('Magento\Backend\Model\View\Result\Forward') + $this->resultForward = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Forward::class) ->disableOriginalConstructor() ->getMock(); - $resultForwardFactory = $this->getMockBuilder('Magento\Backend\Model\View\Result\ForwardFactory') + $resultForwardFactory = $this->getMockBuilder(\Magento\Backend\Model\View\Result\ForwardFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); @@ -71,6 +70,17 @@ protected function setUp() ->method('create') ->willReturn($this->resultForward); + $store = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + + $storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManager::class) + ->disableOriginalConstructor() + ->getMock(); + $storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($store); + $this->action = (new ObjectManager($this))->getObject( NewAction::class, [ @@ -78,6 +88,7 @@ protected function setUp() 'productBuilder' => $this->productBuilder, 'resultPageFactory' => $resultPageFactory, 'resultForwardFactory' => $resultForwardFactory, + 'storeManager' => $storeManager, ] ); diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/ReloadTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/ReloadTest.php index 1ec5d73df5456..4618fda361e35 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/ReloadTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/ReloadTest.php @@ -1,6 +1,6 @@ objectManager = new ObjectManager($this); @@ -86,46 +96,71 @@ protected function setUp() $this->contextMock = $this->getMockBuilder(Context::class) ->disableOriginalConstructor() ->getMock(); + $this->resultFactoryMock = $this->getMockBuilder(ResultFactory::class) ->disableOriginalConstructor() ->getMock(); + $this->layoutMock = $this->getMockBuilder(LayoutInterface::class) ->disableOriginalConstructor() ->getMock(); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) ->getMockForAbstractClass(); + + $this->store = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->productBuilderMock = $this->getMockBuilder(Builder::class) ->disableOriginalConstructor() ->getMock(); + $this->resultMock = $this->getMockBuilder(ResultInterface::class) ->setMethods(['forward', 'setJsonData', 'getLayout']) ->getMockForAbstractClass(); + $this->productMock = $this->getMockBuilder(ProductInterface::class) + ->setMethods([ + 'getStoreId', + 'getTypeId' + ]) ->getMockForAbstractClass(); + $this->uiComponentMock = $this->getMockBuilder(UiComponent::class) ->disableOriginalConstructor() ->getMock(); + $this->processorMock = $this->getMockBuilder(ProcessorInterface::class) ->getMockForAbstractClass(); $this->contextMock->expects($this->any()) ->method('getRequest') ->willReturn($this->requestMock); + $this->resultFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->resultMock); + $this->contextMock->expects($this->any()) ->method('getResultFactory') ->willReturn($this->resultFactoryMock); + $this->productBuilderMock->expects($this->any()) ->method('build') ->willReturn($this->productMock); + $this->layoutMock->expects($this->any()) ->method('getBlock') ->willReturn($this->uiComponentMock); $this->layoutMock->expects($this->any()) ->method('getUpdate') ->willReturn($this->processorMock); + $this->resultMock->expects($this->any()) ->method('getLayout') ->willReturn($this->layoutMock); @@ -134,6 +169,7 @@ protected function setUp() 'context' => $this->contextMock, 'productBuilder' => $this->productBuilderMock, 'layout' => $this->layoutMock, + 'storeManager' => $this->storeManager, ]); } @@ -142,6 +178,7 @@ public function testExecuteToBeRedirect() $this->requestMock->expects($this->once()) ->method('getParam') ->willReturn(false); + $this->resultMock->expects($this->once()) ->method('forward') ->with('noroute') @@ -156,6 +193,10 @@ public function testExecute() ->method('getParam') ->willReturn('true'); + $this->storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($this->store); + $this->assertInstanceOf(ResultInterface::class, $this->model->execute()); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php index 2a8f801dc1d92..53c3617cbae10 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/SaveTest.php @@ -1,6 +1,6 @@ strtr(base64_encode($compareListUrl), '+/=', '-_,'), + Action::PARAM_NAME_URL_ENCODED => '', 'product' => $productId ]; //Verification - $this->urlBuilder->expects($this->at(0)) - ->method('getUrl') - ->with($compareListUrl) - ->will($this->returnValue($compareListUrl)); - $this->urlBuilder->expects($this->at(1)) + $this->urlBuilder->expects($this->once()) ->method('getUrl') ->with($removeUrl) ->will($this->returnValue($removeUrl)); @@ -153,18 +148,12 @@ public function testGetClearListUrl() public function testGetPostDataClearList() { //Data - $refererUrl = 'home/'; $clearUrl = 'catalog/product_compare/clear'; $postParams = [ - Action::PARAM_NAME_URL_ENCODED => strtr(base64_encode($refererUrl), '+/=', '-_,') + Action::PARAM_NAME_URL_ENCODED => '' ]; //Verification - $this->request->expects($this->once()) - ->method('getServer') - ->with('HTTP_REFERER') - ->will($this->returnValue($refererUrl)); - $this->urlBuilder->expects($this->once()) ->method('getUrl') ->with($clearUrl) diff --git a/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php b/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php index 26258cf6f3b11..dda61fde76f11 100644 --- a/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php @@ -1,6 +1,6 @@ ['test_attribute'], 'group_two' => ['attribute_one', 'attribute_two']]; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_merged.xml b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_merged.xml index 131fe397f2e6b..813e9d64af710 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_merged.xml +++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_merged.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_one.xml b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_one.xml index 3e11d226e6af4..3fe4cc449c51d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_one.xml +++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_one.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_two.xml b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_two.xml index 772a85eafe95e..718895e7117fb 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_two.xml +++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Config/_files/attributes_config_two.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/ConfigTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/ConfigTest.php index cce9169113d1c..7f469b6dc1eb5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/ConfigTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/ConfigTest.php @@ -1,6 +1,6 @@ contextMock = $this->getMockBuilder('Magento\Framework\Model\Context') diff --git a/app/code/Magento/Catalog/Test/Unit/Model/FactoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/FactoryTest.php index cec8a7ab9e6d3..514a800b58031 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/FactoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/FactoryTest.php @@ -1,6 +1,6 @@ getMock('Magento\Framework\App\ResourceConnection', [], [], '', false); - $this->connection = $this->getMock('Magento\Framework\DB\Adapter\AdapterInterface'); + $resource = $this->getMock(\Magento\Framework\App\ResourceConnection::class, [], [], '', false); + $this->connection = $this->getMock(\Magento\Framework\DB\Adapter\AdapterInterface::class); $resource->expects($this->any())->method('getConnection')->will($this->returnValue($this->connection)); $this->indexerHelper = $this->getMock( - 'Magento\Catalog\Helper\Product\Flat\Indexer', + \Magento\Catalog\Helper\Product\Flat\Indexer::class, [], [], '', false ); @@ -47,7 +47,7 @@ protected function setUp() [2, 'store_2_flat'], ])); - $this->storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->storeManager = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); $this->model = new \Magento\Catalog\Model\Indexer\Product\Flat\Action\Eraser( $resource, $this->indexerHelper, @@ -58,12 +58,12 @@ protected function setUp() public function testRemoveDeletedProducts() { $productsToDeleteIds = [1, 2]; - $select = $this->getMock('\Magento\Framework\Db\Select', [], [], '', false); + $select = $this->getMock(\Magento\Framework\DB\Select::class, ['from', 'where'], [], '', false); $select->expects($this->once())->method('from')->with('catalog_product_entity')->will($this->returnSelf()); $select->expects($this->once())->method('where')->with('entity_id IN(?)', $productsToDeleteIds) ->will($this->returnSelf()); $products = [['entity_id' => 2]]; - $statement = $this->getMock('\Zend_Db_Statement_Interface'); + $statement = $this->getMock(\Zend_Db_Statement_Interface::class); $statement->expects($this->once())->method('fetchAll')->will($this->returnValue($products)); $this->connection->expects($this->once())->method('query')->with($select) ->will($this->returnValue($statement)); @@ -76,9 +76,9 @@ public function testRemoveDeletedProducts() public function testDeleteProductsFromStoreForAllStores() { - $store1 = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + $store1 = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); $store1->expects($this->any())->method('getId')->will($this->returnValue(1)); - $store2 = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + $store2 = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); $store2->expects($this->any())->method('getId')->will($this->returnValue(2)); $this->storeManager->expects($this->once())->method('getStores') ->will($this->returnValue([$store1, $store2])); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php index 8dc0004e5d1b5..b98464d1f93d5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php @@ -1,6 +1,6 @@ flatIndexerMock = $this->getMockBuilder(\Magento\Catalog\Helper\Product\Flat\Indexer::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resourceMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->tableDataMock = $this->getMockBuilder( + \Magento\Catalog\Model\Indexer\Product\Flat\TableDataInterface::class + )->disableOriginalConstructor()->getMockForAbstractClass(); + $this->connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->metadataPoolMock = $this->getMockBuilder(\Magento\Framework\EntityManager\MetadataPool::class) + ->disableOriginalConstructor() + ->getMock(); + $this->metadataMock = $this->getMockBuilder( + \Magento\Framework\EntityManager\EntityMetadataInterface::class + )->disableOriginalConstructor()->getMockForAbstractClass(); + $this->metadataMock->expects($this->any())->method('getLinkField')->willReturn('entity_id'); + + $this->flatTableBuilder = $objectManagerHelper->getObject( + \Magento\Catalog\Model\Indexer\Product\Flat\FlatTableBuilder::class, + [ + 'productIndexerHelper' => $this->flatIndexerMock, + 'resource' => $this->resourceMock, + 'config' => $this->scopeConfigMock, + 'storeManager' => $this->storeManagerMock, + 'tableData' => $this->tableDataMock, + '_connection' => $this->connectionMock + ] + ); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->flatTableBuilder, + 'metadataPool', + $this->metadataPoolMock + ); + } + + public function testBuild() + { + list($storeId, $changedIds, $valueFieldSuffix, $tableDropSuffix, $fillTmpTables) = [1, [], '', '', true]; + $tableName = 'catalog_product_entity'; + $attributeTable = 'catalog_product_entity_int'; + $temporaryTableName = 'catalog_product_entity_int_tmp_indexer'; + $temporaryValueTableName = 'catalog_product_entity_int_tmp_indexer'; + $linkField = 'entity_id'; + $statusId = 22; + $this->flatIndexerMock->expects($this->once())->method('getAttributes')->willReturn([]); + $this->flatIndexerMock->expects($this->exactly(3))->method('getFlatColumns') + ->willReturnOnConsecutiveCalls( + [], + [$linkField => []], + [$linkField => []] + ); + $this->flatIndexerMock->expects($this->once())->method('getFlatIndexes')->willReturn([]); + $statusAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + $this->flatIndexerMock->expects($this->once())->method('getTablesStructure') + ->willReturn( + [ + 'catalog_product_entity' => [ + $linkField => $statusAttributeMock + ], + 'catalog_product_entity_int' => [ + $linkField => $statusAttributeMock + ] + ] + ); + $this->flatIndexerMock->expects($this->atLeastOnce())->method('getTable') + ->withConsecutive( + [$tableName], + ['catalog_product_website'] + ) + ->willReturn( + $tableName, + 'catalog_product_website' + ); + $this->flatIndexerMock->expects($this->once())->method('getAttribute') + ->with('status') + ->willReturn($statusAttributeMock); + $backendMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend::class) + ->disableOriginalConstructor() + ->getMock(); + $backendMock->expects($this->atLeastOnce())->method('getTable')->willReturn($attributeTable); + $statusAttributeMock->expects($this->atLeastOnce())->method('getBackend')->willReturn( + $backendMock + ); + $statusAttributeMock->expects($this->atLeastOnce())->method('getId')->willReturn($statusId); + $tableMock = $this->getMockBuilder(\Magento\Framework\DB\Ddl\Table::class) + ->disableOriginalConstructor() + ->getMock(); + $this->connectionMock->expects($this->any())->method('newTable')->willReturn($tableMock); + $selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); + $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($selectMock); + $selectMock->expects($this->once())->method('from')->with( + ['et' => 'catalog_product_entity_tmp_indexer'], + [$linkField, 'type_id', 'attribute_set_id'] + )->willReturnSelf(); + $selectMock->expects($this->atLeastOnce())->method('joinInner')->willReturnSelf(); + $selectMock->expects($this->exactly(3))->method('joinLeft') + ->withConsecutive( + [ + ['dstatus' => $attributeTable], + sprintf( + 'e.%s = dstatus.%s AND dstatus.store_id = %s AND dstatus.attribute_id = %s', + $linkField, + $linkField, + $storeId, + $statusId + ), + [] + ], + [ + $temporaryTableName, + "e.{$linkField} = ${temporaryTableName}.{$linkField}", + [$linkField] + ], + [ + $temporaryValueTableName, + "e.${linkField} = " . $temporaryValueTableName . ".${linkField}", + [$linkField] + ] + )->willReturnSelf(); + $this->metadataPoolMock->expects($this->atLeastOnce())->method('getMetadata')->with(ProductInterface::class) + ->willReturn($this->metadataMock); + $storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->storeManagerMock->expects($this->once())->method('getStore')->with($storeId)->willReturn($storeMock); + $this->flatTableBuilder->build($storeId, $changedIds, $valueFieldSuffix, $tableDropSuffix, $fillTmpTables); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Plugin/IndexerConfigDataTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Plugin/IndexerConfigDataTest.php index 77710f27d38ee..e8412dfeecd66 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Plugin/IndexerConfigDataTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Plugin/IndexerConfigDataTest.php @@ -1,6 +1,6 @@ connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $table = $this->getMockBuilder(\Magento\Framework\DB\Ddl\Table::class) + ->disableOriginalConstructor() + ->getMock(); + $table->expects($this->once())->method('addColumn') + ->with('test', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER) + ->willReturnSelf(); + $tableName = 'test_table'; + $this->connectionMock->expects($this->once()) + ->method('newTable') + ->with($tableName) + ->willReturn($table); + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + /** + * @var $builder \Magento\Catalog\Model\Indexer\Product\Flat\Table\Builder + */ + $builder = $objectManagerHelper->getObject( + \Magento\Catalog\Model\Indexer\Product\Flat\Table\Builder::class, + [ + 'connection' => $this->connectionMock, + 'tableName' => $tableName + ] + ); + $this->assertEquals($builder, $builder->addColumn('test', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER)); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/TableDataTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/TableDataTest.php index abc8c10d51a0a..a0884f8d31acc 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/TableDataTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/TableDataTest.php @@ -1,6 +1,6 @@ getMockForAbstractClass('\Magento\Framework\App\ScopeResolverInterface', [], '', false); - $localeResolver = $this->getMockForAbstractClass('\Magento\Framework\Locale\ResolverInterface', [], '', false); - $currencyFactory = $this->getMock('\Magento\Directory\Model\CurrencyFactory', [], [], '', false); - $localeFormat = $objectHelper->getObject( - 'Magento\Framework\Locale\Format', + $localeFormat = $objectHelper->getObject(\Magento\Framework\Locale\Format::class); + $this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->getMockForAbstractClass(); + $this->scopeOverriddenValue = $this->getMockBuilder( + \Magento\Catalog\Model\Attribute\ScopeOverriddenValue::class + ) + ->disableOriginalConstructor() + ->getMock(); + $this->model = $objectHelper->getObject( + \Magento\Catalog\Model\Product\Attribute\Backend\Price::class, [ - 'scopeResolver' => $scopeResolver, - 'localeResolver' => $localeResolver, - 'currencyFactory' => $currencyFactory, + 'localeFormat' => $localeFormat, + 'storeManager' => $this->storeManager, + 'scopeOverriddenValue' => $this->scopeOverriddenValue ] ); - // the model we are testing - $this->model = $objectHelper->getObject( - 'Magento\Catalog\Model\Product\Attribute\Backend\Price', - ['localeFormat' => $localeFormat] - ); - - $attribute = $this->getMockForAbstractClass( - '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute', - [], - '', - false - ); - $this->model->setAttribute($attribute); + $this->attribute = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) + ->setMethods(['getAttributeCode', 'isScopeWebsite']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->model->setAttribute($this->attribute); } /** @@ -81,7 +95,7 @@ public function dataProviderValidate() */ public function testValidateForFailure($value) { - $object = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false); + $object = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); $object->expects($this->once())->method('getData')->willReturn($value); $this->model->validate($object); @@ -101,4 +115,69 @@ public function dataProviderValidateForFailure() 'negative Lebanon' => ['-1 234'], ]; } + + public function testAfterSaveWithDifferentStores() + { + $newPrice = '9.99'; + $attributeCode = 'price'; + $defaultStoreId = 0; + $websiteStoreIds = [1, 2, 3]; + $object = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)->disableOriginalConstructor()->getMock(); + $object->expects($this->any())->method('getData')->with($attributeCode)->willReturn($newPrice); + $object->expects($this->any())->method('getOrigData')->with($attributeCode)->willReturn('7.77'); + $object->expects($this->any())->method('getStoreId')->willReturn($defaultStoreId); + $object->expects($this->any())->method('getWebsiteStoreIds')->willReturn($websiteStoreIds); + $this->attribute->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode); + $this->attribute->expects($this->any())->method('isScopeWebsite') + ->willReturn(\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE); + + $object->expects($this->any())->method('addAttributeUpdate')->withConsecutive( + [ + $this->equalTo($attributeCode), + $this->equalTo($newPrice), + $this->equalTo($websiteStoreIds[0]) + ], + [ + $this->equalTo($attributeCode), + $this->equalTo($newPrice), + $this->equalTo($websiteStoreIds[1]) + ], + [ + $this->equalTo($attributeCode), + $this->equalTo($newPrice), + $this->equalTo($websiteStoreIds[2]) + ] + ); + $this->assertEquals($this->model, $this->model->afterSave($object)); + } + + public function testAfterSaveWithOldPrice() + { + $attributeCode = 'price'; + + $object = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)->disableOriginalConstructor()->getMock(); + $object->expects($this->any())->method('getData')->with($attributeCode)->willReturn('7.77'); + $object->expects($this->any())->method('getOrigData')->with($attributeCode)->willReturn('7.77'); + $this->attribute->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode); + $this->attribute->expects($this->any())->method('getIsGlobal') + ->willReturn(\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE); + + $object->expects($this->never())->method('addAttributeUpdate'); + $this->assertEquals($this->model, $this->model->afterSave($object)); + } + + public function testAfterSaveWithGlobalPrice() + { + $attributeCode = 'price'; + + $object = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)->disableOriginalConstructor()->getMock(); + $object->expects($this->any())->method('getData')->with($attributeCode)->willReturn('9.99'); + $object->expects($this->any())->method('getOrigData')->with($attributeCode)->willReturn('7.77'); + $this->attribute->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode); + $this->attribute->expects($this->any())->method('getIsGlobal') + ->willReturn(\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL); + + $object->expects($this->never())->method('addAttributeUpdate'); + $this->assertEquals($this->model, $this->model->afterSave($object)); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php index 3cd1922622f0e..74a42fa2cc845 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php @@ -1,6 +1,6 @@ objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->stockRegistry = $this->getMockBuilder('Magento\CatalogInventory\Model\StockRegistry') + $this->stockRegistry = $this->getMockBuilder(\Magento\CatalogInventory\Model\StockRegistry::class) ->disableOriginalConstructor() ->setMethods(['getStockItem', '__wakeup']) ->getMock(); $this->stockItemMock = $this->getMock( - 'Magento\CatalogInventory\Model\Stock\Item', + \Magento\CatalogInventory\Model\Stock\Item::class, ['getIsInStock', 'getQty', '__wakeup'], [], '', @@ -47,10 +47,10 @@ protected function setUp() ->method('getStockItem') ->will($this->returnValue($this->stockItemMock)); $this->model = $this->objectHelper->getObject( - 'Magento\Catalog\Model\Product\Attribute\Backend\Stock', + \Magento\Catalog\Model\Product\Attribute\Backend\Stock::class, ['stockRegistry' => $this->stockRegistry] ); - $attribute = $this->getMock('Magento\Framework\DataObject', ['getAttributeCode']); + $attribute = $this->getMock(\Magento\Framework\DataObject::class, ['getAttributeCode']); $attribute->expects($this->atLeastOnce()) ->method('getAttributeCode') ->will($this->returnValue(self::ATTRIBUTE_NAME)); @@ -64,7 +64,7 @@ public function testAfterLoad() $this->stockItemMock->expects($this->once())->method('getIsInStock')->will($this->returnValue(1)); $this->stockItemMock->expects($this->once())->method('getQty')->will($this->returnValue(5)); - $store = $this->getMock('Magento\Store\Model\Store', ['getWebsiteId', '__wakeup'], [], '', false); + $store = $this->getMock(\Magento\Store\Model\Store::class, ['getWebsiteId', '__wakeup'], [], '', false); $store->expects($this->once()) ->method('getWebsiteId') ->will($this->returnValue(10)); @@ -125,4 +125,17 @@ public function testBeforeSaveQtyIsZero() $stockData = $object->getStockData(); $this->assertEquals(0, $stockData['qty']); } + + public function testBeforeSaveNoStockData() + { + $object = new \Magento\Framework\DataObject( + [ + self::ATTRIBUTE_NAME => ['is_in_stock' => 1, 'qty' => 0] + ] + ); + + $this->model->beforeSave($object); + $this->assertNull($object->getStockData()); + $this->assertNull($object->getData(self::ATTRIBUTE_NAME)); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/WeightTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/WeightTest.php index fd5ea0fbd3677..b2a33e76a953a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/WeightTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/WeightTest.php @@ -1,6 +1,6 @@ productMock->expects($this->once())->method('getMediaGalleryEntries') ->willReturn([$existingEntryMock]); $entryMock->expects($this->once())->method('getId')->willReturn($entryId); + $entryMock->expects($this->once())->method('getFile')->willReturn("base64"); + $entryMock->expects($this->once())->method('setId')->with(null); $this->productMock->expects($this->once())->method('setMediaGalleryEntries') ->willReturn([$entryMock]); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/MimeTypeExtensionMapTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/MimeTypeExtensionMapTest.php index ebf351da74102..8ec55bcec098a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/MimeTypeExtensionMapTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/MimeTypeExtensionMapTest.php @@ -1,7 +1,7 @@ objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->attributeRepository = $this->getMock( + 'Magento\Catalog\Model\Product\Attribute\Repository', + ['get'], + [], + '', + false + ); + $this->model = $this->objectHelper->getObject( + \Magento\Catalog\Model\Product\Gallery\ReadHandler::class, + [ + 'attributeRepository' => $this->attributeRepository, + ] + ); + } + + public function testAddMediaDataToProduct() + { + $attribute = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + + $attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue('image')); + + $this->attributeRepository->expects($this->once()) + ->method('get') + ->with('media_gallery') + ->willReturn($attribute); + + $product = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->getMock(); + $product->expects($this->once())->method('setData')->with( + 'image', + [ + 'images' =>[ + 10 => ['value_id' => 10,] + ], + 'values' => [] + ] + ); + $this->model->addMediaDataToProduct($product, [['value_id' => 10]]); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php index 3d6608d595121..d4882c7c9959a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php @@ -1,6 +1,6 @@ image->setBaseFile('/somefile.png'); $this->assertEquals('catalog/product/somefile.png', $this->image->getBaseFile()); $this->assertEquals( - 'catalog/product/cache/1//beff4985b56e3afdbeabfc89641a4582/somefile.png', + 'catalog/product/cache//beff4985b56e3afdbeabfc89641a4582/somefile.png', $this->image->getNewFile() ); } @@ -300,7 +300,7 @@ public function testGetUrl() $this->testSetGetBaseFile(); $url = $this->image->getUrl(); $this->assertEquals( - 'http://magento.com/media/catalog/product/cache/1//beff4985b56e3afdbeabfc89641a4582/somefile.png', + 'http://magento.com/media/catalog/product/cache//beff4985b56e3afdbeabfc89641a4582/somefile.png', $url ); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Initialization/Helper/ProductLinksTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Initialization/Helper/ProductLinksTest.php index c5f35d7dc8960..9bc5e82fe6801 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Initialization/Helper/ProductLinksTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Initialization/Helper/ProductLinksTest.php @@ -1,6 +1,6 @@ objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->rootDirectory = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface') + $this->filesystemMock = $this->getMockBuilder(Filesystem::class) ->disableOriginalConstructor() - ->setMethods(['isFile', 'isReadable', 'getAbsolutePath']) - ->getMockForAbstractClass(); + ->getMock(); + + $this->rootDirectory = $this->getMockBuilder(ReadInterface::class) + ->getMock(); + + $this->filesystemMock->expects($this->once()) + ->method('getDirectoryRead') + ->with(DirectoryList::MEDIA, DriverPool::FILE) + ->willReturn($this->rootDirectory); $this->coreFileStorageDatabase = $this->getMock( - 'Magento\MediaStorage\Helper\File\Storage\Database', + \Magento\MediaStorage\Helper\File\Storage\Database::class, ['copyFile'], [], '', @@ -46,28 +64,29 @@ protected function setUp() protected function getFileObject() { return $this->objectManager->getObject( - 'Magento\Catalog\Model\Product\Option\Type\File', + \Magento\Catalog\Model\Product\Option\Type\File::class, [ - 'saleableItem' => $this->rootDirectory, - 'priceCurrency' => $this->coreFileStorageDatabase + 'filesystem' => $this->filesystemMock, + 'coreFileStorageDatabase' => $this->coreFileStorageDatabase ] ); } public function testCopyQuoteToOrder() { - $optionMock = $this->getMockBuilder( - 'Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface' - )->disableOriginalConstructor()->setMethods(['getValue'])->getMockForAbstractClass(); + $optionMock = $this->getMockBuilder(OptionInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getValue']) + ->getMockForAbstractClass(); $quotePath = '/quote/path/path/uploaded.file'; $orderPath = '/order/path/path/uploaded.file'; $optionMock->expects($this->any()) ->method('getValue') - ->will($this->returnValue(['quote_path' => $quotePath, 'order_path' => $orderPath])); + ->will($this->returnValue(serialize(['quote_path' => $quotePath, 'order_path' => $orderPath]))); - $this->rootDirectory->expects($this->any()) + $this->rootDirectory->expects($this->once()) ->method('isFile') ->with($this->equalTo($quotePath)) ->will($this->returnValue(true)); @@ -89,7 +108,7 @@ public function testCopyQuoteToOrder() $fileObject->setData('configuration_item_option', $optionMock); $this->assertInstanceOf( - 'Magento\Catalog\Model\Product\Option\Type\File', + \Magento\Catalog\Model\Product\Option\Type\File::class, $fileObject->copyQuoteToOrder() ); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/UrlBuilderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/UrlBuilderTest.php index fa295d795417c..7e989caafd9ba 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/UrlBuilderTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Option/UrlBuilderTest.php @@ -1,6 +1,6 @@ product = $this->getMock( + \Magento\Catalog\Model\Product::class, + ['__wakeup', 'getCanShowPrice', 'isSalable'], + [], + '', + false + ); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->object = $objectManager->getObject( + \Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolver::class + ); + } + + public function testSalableItem() + { + $this->product->expects($this->any()) + ->method('getCanShowPrice') + ->willReturn(true); + + $this->product->expects($this->any())->method('isSalable')->willReturn(true); + + $result = $this->object->isSalable($this->product); + $this->assertTrue($result); + } + + public function testNotSalableItem() + { + $this->product->expects($this->any()) + ->method('getCanShowPrice') + ->willReturn(true); + + $this->product->expects($this->any())->method('isSalable')->willReturn(false); + + $result = $this->object->isSalable($this->product); + $this->assertFalse($result); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php index 063f85ae4f360..69503bda452ea 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/product_options_valid.xml b/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/product_options_valid.xml index 093521a0b7a49..5f418c4b177ad 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/product_options_valid.xml +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductOptions/Config/_files/product_options_valid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index f2be2fc92b835..61819a215e60b 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -1,7 +1,7 @@ model->setTypeId('typeId'); $this->model->getTypeInstance(); } + + public function testGetOptionById() + { + $optionId = 100; + $optionMock = $this->getMock(\Magento\Catalog\Model\Product\Option::class, [], [], '', false); + $this->model->setOptions([$optionMock]); + $optionMock->expects($this->once())->method('getId')->willReturn($optionId); + $this->assertEquals($optionMock, $this->model->getOptionById($optionId)); + } + + public function testGetOptionByIdWithWrongOptionId() + { + $optionId = 100; + $optionMock = $this->getMock(\Magento\Catalog\Model\Product\Option::class, [], [], '', false); + $this->model->setOptions([$optionMock]); + $optionMock->expects($this->once())->method('getId')->willReturn(200); + $this->assertNull($this->model->getOptionById($optionId)); + } + + public function testGetOptionByIdForProductWithoutOptions() + { + $this->assertNull($this->model->getOptionById(100)); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypeListTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypeListTest.php index a8aab0838ffc5..3c4e1fb3fc052 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypeListTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypeListTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types.xml b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types.xml index 525beaf93c6e9..dc5284d1e5405 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types.xml +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml index 96a8c06c1db2a..724203272620b 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/Config/_files/valid_product_types_merged.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php index d22f4dc10923d..0c5d7e98095bb 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php @@ -1,6 +1,6 @@ disableOriginalConstructor() ->getMock(); - $entityMock = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity') + $this->entityMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class) ->disableOriginalConstructor() ->getMock(); + $this->galleryResourceMock = $this->getMockBuilder( + \Magento\Catalog\Model\ResourceModel\Product\Gallery::class + )->disableOriginalConstructor()->getMock(); + + $this->metadataPoolMock = $this->getMockBuilder( + \Magento\Framework\EntityManager\MetadataPool::class + )->disableOriginalConstructor()->getMock(); + + $this->galleryReadHandlerMock = $this->getMockBuilder( + \Magento\Catalog\Model\Product\Gallery\ReadHandler::class + )->disableOriginalConstructor()->getMock(); + $storeManager->expects($this->any())->method('getId')->willReturn(1); $storeManager->expects($this->any())->method('getStore')->willReturnSelf(); $universalFactory->expects($this->exactly(1))->method('create')->willReturnOnConsecutiveCalls( - $entityMock + $this->entityMock ); - $entityMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock); - $entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]); - $entityMock->expects($this->any())->method('getTable')->willReturnArgument(0); + $this->entityMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock); + $this->entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]); + $this->entityMock->expects($this->any())->method('getTable')->willReturnArgument(0); $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); $helper = new ObjectManager($this); @@ -117,6 +149,18 @@ protected function setUp() [ 'Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation', $this->getMock('Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation') + ], + [ + \Magento\Catalog\Model\ResourceModel\Product\Gallery::class, + $this->galleryResourceMock + ], + [ + \Magento\Framework\EntityManager\MetadataPool::class, + $this->metadataPoolMock + ], + [ + \Magento\Catalog\Model\Product\Gallery\ReadHandler::class, + $this->galleryReadHandlerMock ] ]); $this->collection = $helper->getObject( @@ -173,6 +217,47 @@ public function testAddProductCategoriesFilter() $this->collection->addCategoriesFilter([$conditionType => $values]); } + public function testAddMediaGalleryData() + { + $attributeId = 42; + $itemId = 4242; + $linkField = 'entity_id'; + $mediaGalleriesMock = [[$linkField => $itemId]]; + $itemMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->getMock(); + $attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) + ->disableOriginalConstructor() + ->getMock(); + $selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class) + ->disableOriginalConstructor() + ->getMock(); + $metadataMock = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->collection->addItem($itemMock); + $reflection = new \ReflectionClass(get_class($this->collection)); + $reflectionProperty = $reflection->getProperty('_isCollectionLoaded'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->collection, true); + + $this->galleryResourceMock->expects($this->once())->method('createBatchBaseSelect')->willReturn($selectMock); + $attributeMock->expects($this->once())->method('getAttributeId')->willReturn($attributeId); + $this->entityMock->expects($this->once())->method('getAttribute')->willReturn($attributeMock); + $itemMock->expects($this->atLeastOnce())->method('getId')->willReturn($itemId); + $selectMock->expects($this->once())->method('where')->with('entity.' . $linkField . ' IN (?)', [$itemId]); + $this->metadataPoolMock->expects($this->once())->method('getMetadata')->willReturn($metadataMock); + $metadataMock->expects($this->once())->method('getLinkField')->willReturn($linkField); + + $this->connectionMock->expects($this->once())->method('fetchAll')->with($selectMock)->willReturn( + [['entity_id' => $itemId]] + ); + $this->galleryReadHandlerMock->expects($this->once())->method('addMediaDataToProduct') + ->with($itemMock, $mediaGalleriesMock); + + $this->assertSame($this->collection, $this->collection->addMediaGalleryData()); + } + /** * @param $map */ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php new file mode 100644 index 0000000000000..30060c81883eb --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php @@ -0,0 +1,54 @@ +objectManager = new ObjectManager($this); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + */ + public function testInitializeWithWrongProcessorInstance() + { + $processorValid = $this->getMock(BaseSelectProcessorInterface::class); + $processorInvalid = $this->getMock(\stdClass::class); + + $this->objectManager->getObject(CompositeBaseSelectProcessor::class, [ + 'baseSelectProcessors' => [$processorValid, $processorInvalid], + ]); + } + + public function testProcess() + { + $select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $processorFirst = $this->getMock(BaseSelectProcessorInterface::class); + $processorFirst->expects($this->once())->method('process')->with($select)->willReturn($select); + + $processorSecond = $this->getMock(BaseSelectProcessorInterface::class); + $processorSecond->expects($this->once())->method('process')->with($select)->willReturn($select); + + /** @var CompositeBaseSelectProcessor $baseSelectProcessors */ + $baseSelectProcessors = $this->objectManager->getObject(CompositeBaseSelectProcessor::class, [ + 'baseSelectProcessors' => [$processorFirst, $processorSecond], + ]); + $this->assertEquals($select, $baseSelectProcessors->process($select)); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/FlatTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/FlatTest.php index 28c7f8002e5f5..e18475cb1ec11 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/FlatTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/FlatTest.php @@ -1,6 +1,6 @@ willReturnSelf(); $this->product->expects($this->at(0))->method('getData')->with('entity_id')->willReturn($productId); $this->product->expects($this->at(1))->method('getStoreId')->will($this->returnValue($storeId)); - $this->connection->expects($this->exactly(3))->method('quoteInto')->withConsecutive( - ['value.store_id = ?', 1], - ['value.entity_id = ?', 5], - ['default_value.entity_id = ?', 5] + $this->connection->expects($this->exactly(2))->method('quoteInto')->withConsecutive( + ['value.store_id = ?'], + ['default_value.store_id = ?'] )->willReturnOnConsecutiveCalls( 'value.store_id = ' . $storeId, - 'value.entity_id = ' . $productId, - 'default_value.entity_id = ' . $productId + 'default_value.store_id = ' . 0 ); $this->select->expects($this->at(2))->method('joinLeft')->with( ['value' => $getTableReturnValue], @@ -369,8 +367,7 @@ public function testLoadGallery() )->willReturnSelf(); $this->select->expects($this->at(3))->method('joinLeft')->with( ['default_value' => $getTableReturnValue], - 'main.value_id = default_value.value_id AND default_value.store_id = 0 AND default_value.entity_id = ' - . $productId, + 'main.value_id = default_value.value_id AND default_value.store_id = 0', ['label_default' => 'label', 'position_default' => 'position', 'disabled_default' => 'disabled'] )->willReturnSelf(); $this->select->expects($this->at(4))->method('where')->with( @@ -378,7 +375,7 @@ public function testLoadGallery() $attributeId )->willReturnSelf(); $this->select->expects($this->at(5))->method('where')->with('main.disabled = 0')->willReturnSelf(); - $this->select->expects($this->at(6))->method('where') + $this->select->expects($this->at(7))->method('where') ->with('entity.entity_id = ?', $productId) ->willReturnSelf(); $this->select->expects($this->once())->method('order') diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php index 429440a2a1983..ab4d90f7f7c66 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php @@ -1,6 +1,6 @@ eavConfig = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); + $this->metadataPool = $this->getMockBuilder(MetadataPool::class)->disableOriginalConstructor()->getMock(); + $this->storeResolver = $this->getMockBuilder(StoreResolverInterface::class)->getMock(); + $this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $this->statusBaseSelectProcessor = (new ObjectManager($this))->getObject(StatusBaseSelectProcessor::class, [ + 'eavConfig' => $this->eavConfig, + 'metadataPool' => $this->metadataPool, + 'storeResolver' => $this->storeResolver, + ]); + } + + public function testProcess() + { + $linkField = 'link_field'; + $backendTable = 'backend_table'; + $attributeId = 2; + $currentStoreId = 1; + + $metadata = $this->getMock(EntityMetadataInterface::class); + $metadata->expects($this->once()) + ->method('getLinkField') + ->willReturn($linkField); + $this->metadataPool->expects($this->once()) + ->method('getMetadata') + ->with(ProductInterface::class) + ->willReturn($metadata); + + /** @var AttributeInterface|\PHPUnit_Framework_MockObject_MockObject $statusAttribute */ + $statusAttribute = $this->getMockBuilder(AttributeInterface::class) + ->setMethods(['getBackendTable', 'getAttributeId']) + ->getMock(); + $statusAttribute->expects($this->atLeastOnce()) + ->method('getBackendTable') + ->willReturn($backendTable); + $statusAttribute->expects($this->atLeastOnce()) + ->method('getAttributeId') + ->willReturn($attributeId); + $this->eavConfig->expects($this->once()) + ->method('getAttribute') + ->with(Product::ENTITY, ProductInterface::STATUS) + ->willReturn($statusAttribute); + + $this->storeResolver->expects($this->once()) + ->method('getCurrentStoreId') + ->willReturn($currentStoreId); + + $this->select->expects($this->at(0)) + ->method('joinLeft') + ->with( + ['status_global_attr' => $backendTable], + "status_global_attr.{$linkField} = " + . BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . " AND status_global_attr.attribute_id = {$attributeId}" + . ' AND status_global_attr.store_id = ' . Store::DEFAULT_STORE_ID, + [] + ) + ->willReturnSelf(); + $this->select->expects($this->at(1)) + ->method('joinLeft') + ->with( + ['status_attr' => $backendTable], + "status_attr.{$linkField} = " . BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . " AND status_attr.attribute_id = {$attributeId}" + . " AND status_attr.store_id = {$currentStoreId}", + [] + ) + ->willReturnSelf(); + $this->select->expects($this->at(2)) + ->method('where') + ->with('IFNULL(status_attr.value, status_global_attr.value) = ?', Status::STATUS_ENABLED) + ->willReturnSelf(); + + $this->assertEquals($this->select, $this->statusBaseSelectProcessor->process($this->select)); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php index f52394070659c..a0269e62ef251 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/Test/Unit/Observer/MenuCategoryDataTest.php b/app/code/Magento/Catalog/Test/Unit/Observer/MenuCategoryDataTest.php index 44a9a00716fad..23ea2bc891748 100644 --- a/app/code/Magento/Catalog/Test/Unit/Observer/MenuCategoryDataTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Observer/MenuCategoryDataTest.php @@ -1,6 +1,6 @@ product = $this->getMock( - 'Magento\Catalog\Model\Product', + \Magento\Catalog\Model\Product::class, ['getPriceInfo', '__wakeup', 'getCanShowPrice'], [], '', false ); - $this->priceInfo = $this->getMock('Magento\Framework\Pricing\PriceInfo', ['getPrice'], [], '', false); + $this->priceInfo = $this->getMock( + \Magento\Framework\Pricing\PriceInfoInterface::class, + [ + 'getPrice', + 'getPrices', + 'getAdjustments', + 'getAdjustment' + ], + [], + '', + false + ); $this->product->expects($this->any()) ->method('getPriceInfo') ->will($this->returnValue($this->priceInfo)); - $eventManager = $this->getMock('Magento\Framework\Event\Test\Unit\ManagerStub', [], [], '', false); - $config = $this->getMock('Magento\Store\Model\Store\Config', [], [], '', false); - $this->layout = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); + $eventManager = $this->getMock(\Magento\Framework\Event\Test\Unit\ManagerStub::class, [], [], '', false); + $config = $this->getMock(\Magento\Store\Api\Data\StoreConfigInterface::class, [], [], '', false); + $this->layout = $this->getMock(\Magento\Framework\View\Layout::class, [], [], '', false); - $this->priceBox = $this->getMock('Magento\Framework\Pricing\Render\PriceBox', [], [], '', false); - $this->logger = $this->getMock('Psr\Log\LoggerInterface'); + $this->priceBox = $this->getMock(\Magento\Framework\Pricing\Render\PriceBox::class, [], [], '', false); + $this->logger = $this->getMock(\Psr\Log\LoggerInterface::class); - $this->layout->expects($this->any()) - ->method('getBlock') - ->will($this->returnValue($this->priceBox)); + $this->layout->expects($this->any())->method('getBlock')->willReturn($this->priceBox); $cacheState = $this->getMockBuilder(\Magento\Framework\App\Cache\StateInterface::class) ->getMockForAbstractClass(); - $scopeConfigMock = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface'); - $context = $this->getMock('Magento\Framework\View\Element\Template\Context', [], [], '', false); + $appState = $this->getMockBuilder(\Magento\Framework\App\State::class) + ->disableOriginalConstructor() + ->getMock(); + + $resolver = $this->getMockBuilder(\Magento\Framework\View\Element\Template\File\Resolver::class) + ->disableOriginalConstructor() + ->getMock(); + + $urlBuilder = $this->getMockBuilder(\Magento\Framework\UrlInterface::class)->getMockForAbstractClass(); + + $store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)->getMockForAbstractClass(); + $storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->setMethods(['getStore', 'getCode']) + ->getMockForAbstractClass(); + $storeManager->expects($this->any())->method('getStore')->will($this->returnValue($store)); + + $scopeConfigMock = $this->getMockForAbstractClass(\Magento\Framework\App\Config\ScopeConfigInterface::class); + $context = $this->getMock(\Magento\Framework\View\Element\Template\Context::class, [], [], '', false); $context->expects($this->any()) ->method('getEventManager') ->will($this->returnValue($eventManager)); @@ -104,32 +148,72 @@ protected function setUp() $context->expects($this->any()) ->method('getCacheState') ->will($this->returnValue($cacheState)); + $context->expects($this->any()) + ->method('getStoreManager') + ->will($this->returnValue($storeManager)); + $context->expects($this->any()) + ->method('getAppState') + ->will($this->returnValue($appState)); + $context->expects($this->any()) + ->method('getResolver') + ->will($this->returnValue($resolver)); + $context->expects($this->any()) + ->method('getUrlBuilder') + ->will($this->returnValue($urlBuilder)); - $this->rendererPool = $this->getMockBuilder('Magento\Framework\Pricing\Render\RendererPool') + $this->rendererPool = $this->getMockBuilder(\Magento\Framework\Pricing\Render\RendererPool::class) ->disableOriginalConstructor() ->getMock(); - $this->price = $this->getMock('Magento\Framework\Pricing\Price\PriceInterface'); + $this->price = $this->getMock(\Magento\Framework\Pricing\Price\PriceInterface::class); $this->price->expects($this->any()) ->method('getPriceCode') ->will($this->returnValue(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE)); - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->object = $objectManager->getObject( - 'Magento\Catalog\Pricing\Render\FinalPriceBox', + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->salableResolverMock = $this->getMockBuilder(SalableResolverInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->object = $this->objectManager->getObject( + \Magento\Catalog\Pricing\Render\FinalPriceBox::class, [ 'context' => $context, 'saleableItem' => $this->product, 'rendererPool' => $this->rendererPool, 'price' => $this->price, - 'data' => ['zone' => 'test_zone'] + 'data' => ['zone' => 'test_zone', 'list_category_page' => true], + 'salableResolver' => $this->salableResolverMock ] ); + + $this->moduleManager = $this->getMockBuilder(Manager::class) + ->setMethods(['isEnabled', 'isOutputEnabled']) + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManager->setBackwardCompatibleProperty( + $this->object, + 'moduleManager', + $this->moduleManager + ); } public function testRenderMsrpDisabled() { - $priceType = $this->getMock('Magento\Msrp\Pricing\Price\MsrpPrice', [], [], '', false); + $priceType = $this->getMock(\Magento\Msrp\Pricing\Price\MsrpPrice::class, [], [], '', false); + + $this->moduleManager->expects(self::once()) + ->method('isEnabled') + ->with('Magento_Msrp') + ->willReturn(true); + + $this->moduleManager->expects(self::once()) + ->method('isOutputEnabled') + ->with('Magento_Msrp') + ->willReturn(true); + $this->priceInfo->expects($this->once()) ->method('getPrice') ->with($this->equalTo('msrp_price')) @@ -150,7 +234,18 @@ public function testRenderMsrpDisabled() public function testRenderMsrpEnabled() { - $priceType = $this->getMock('Magento\Msrp\Pricing\Price\MsrpPrice', [], [], '', false); + $priceType = $this->getMock(\Magento\Msrp\Pricing\Price\MsrpPrice::class, [], [], '', false); + + $this->moduleManager->expects(self::once()) + ->method('isEnabled') + ->with('Magento_Msrp') + ->willReturn(true); + + $this->moduleManager->expects(self::once()) + ->method('isOutputEnabled') + ->with('Magento_Msrp') + ->willReturn(true); + $this->priceInfo->expects($this->once()) ->method('getPrice') ->with($this->equalTo('msrp_price')) @@ -166,7 +261,7 @@ public function testRenderMsrpEnabled() ->with($this->equalTo($this->product)) ->will($this->returnValue(true)); - $priceBoxRender = $this->getMockBuilder('Magento\Framework\Pricing\Render\PriceBox') + $priceBoxRender = $this->getMockBuilder(\Magento\Framework\Pricing\Render\PriceBox::class) ->disableOriginalConstructor() ->getMock(); $priceBoxRender->expects($this->once()) @@ -193,6 +288,16 @@ public function testRenderMsrpEnabled() public function testRenderMsrpNotRegisteredException() { + $this->moduleManager->expects(self::once()) + ->method('isEnabled') + ->with('Magento_Msrp') + ->willReturn(true); + + $this->moduleManager->expects(self::once()) + ->method('isOutputEnabled') + ->with('Magento_Msrp') + ->willReturn(true); + $this->logger->expects($this->once()) ->method('critical'); @@ -211,21 +316,22 @@ public function testRenderMsrpNotRegisteredException() public function testRenderAmountMinimal() { - $priceType = $this->getMock('Magento\Catalog\Pricing\Price\FinalPrice', [], [], '', false); - $amount = $this->getMockForAbstractClass('Magento\Framework\Pricing\Amount\AmountInterface'); + $priceType = $this->getMock(\Magento\Catalog\Pricing\Price\FinalPrice::class, [], [], '', false); + $amount = $this->getMockForAbstractClass(\Magento\Framework\Pricing\Amount\AmountInterface::class); $priceId = 'price_id'; $html = 'html'; $this->object->setData('price_id', $priceId); $arguments = [ 'zone' => 'test_zone', + 'list_category_page' => true, 'display_label' => 'As low as', 'price_id' => $priceId, 'include_container' => false, 'skip_adjustments' => true, ]; - $amountRender = $this->getMock('Magento\Framework\Pricing\Render\Amount', ['toHtml'], [], '', false); + $amountRender = $this->getMock(\Magento\Framework\Pricing\Render\Amount::class, ['toHtml'], [], '', false); $amountRender->expects($this->once()) ->method('toHtml') ->will($this->returnValue($html)); @@ -255,10 +361,10 @@ public function testRenderAmountMinimal() */ public function testHasSpecialPrice($regularPrice, $finalPrice, $expectedResult) { - $regularPriceType = $this->getMock('Magento\Catalog\Pricing\Price\RegularPrice', [], [], '', false); - $finalPriceType = $this->getMock('Magento\Catalog\Pricing\Price\FinalPrice', [], [], '', false); - $regularPriceAmount = $this->getMockForAbstractClass('Magento\Framework\Pricing\Amount\AmountInterface'); - $finalPriceAmount = $this->getMockForAbstractClass('Magento\Framework\Pricing\Amount\AmountInterface'); + $regularPriceType = $this->getMock(\Magento\Catalog\Pricing\Price\RegularPrice::class, [], [], '', false); + $finalPriceType = $this->getMock(\Magento\Catalog\Pricing\Price\FinalPrice::class, [], [], '', false); + $regularPriceAmount = $this->getMockForAbstractClass(\Magento\Framework\Pricing\Amount\AmountInterface::class); + $finalPriceAmount = $this->getMockForAbstractClass(\Magento\Framework\Pricing\Amount\AmountInterface::class); $regularPriceAmount->expects($this->once()) ->method('getValue') @@ -303,10 +409,10 @@ public function testShowMinimalPrice() $this->object->setDisplayMinimalPrice($displayMininmalPrice); - $finalPriceType = $this->getMock('Magento\Catalog\Pricing\Price\FinalPrice', [], [], '', false); + $finalPriceType = $this->getMock(\Magento\Catalog\Pricing\Price\FinalPrice::class, [], [], '', false); - $finalPriceAmount = $this->getMockForAbstractClass('Magento\Framework\Pricing\Amount\AmountInterface'); - $minimalPriceAmount = $this->getMockForAbstractClass('Magento\Framework\Pricing\Amount\AmountInterface'); + $finalPriceAmount = $this->getMockForAbstractClass(\Magento\Framework\Pricing\Amount\AmountInterface::class); + $minimalPriceAmount = $this->getMockForAbstractClass(\Magento\Framework\Pricing\Amount\AmountInterface::class); $finalPriceAmount->expects($this->once()) ->method('getValue') @@ -338,4 +444,100 @@ public function testHidePrice() $this->assertEmpty($this->object->toHtml()); } + + public function testGetCacheKey() + { + $result = $this->object->getCacheKey(); + $this->assertStringEndsWith('list-category-page', $result); + } + + public function testGetCacheKeyInfoContainsDisplayMinimalPrice() + { + $this->assertArrayHasKey('display_minimal_price', $this->object->getCacheKeyInfo()); + } + + public function testRenderMsrpModuleDisabled() + { + $this->moduleManager->expects(self::exactly(2)) + ->method('isEnabled') + ->with('Magento_Msrp') + ->will($this->onConsecutiveCalls(false, true)); + + $this->priceInfo->expects($this->never()) + ->method('getPrice'); + + $result = $this->object->toHtml(); + + //assert price wrapper + $this->assertStringStartsWith('assertRegExp('/[final_price]/', $result); + + $this->moduleManager->expects(self::once()) + ->method('isOutputEnabled') + ->with('Magento_Msrp') + ->willReturn(false); + + $result = $this->object->toHtml(); + + //assert price wrapper + $this->assertStringStartsWith('assertRegExp('/[final_price]/', $result); + } + + /** + * Test when is_product_list flag is not specified + */ + public function testGetCacheKeyInfoContainsIsProductListFlagByDefault() + { + $cacheInfo = $this->object->getCacheKeyInfo(); + self::assertArrayHasKey('is_product_list', $cacheInfo); + self::assertFalse($cacheInfo['is_product_list']); + } + + /** + * Test when is_product_list flag is specified + * + * @param bool $flag + * @dataProvider isProductListDataProvider + */ + public function testGetCacheKeyInfoContainsIsProductListFlag($flag) + { + $this->object->setData('is_product_list', $flag); + $cacheInfo = $this->object->getCacheKeyInfo(); + self::assertArrayHasKey('is_product_list', $cacheInfo); + self::assertEquals($flag, $cacheInfo['is_product_list']); + } + + /** + * Test when is_product_list flag is not specified + */ + public function testIsProductListByDefault() + { + self::assertFalse($this->object->isProductList()); + } + + /** + * Test when is_product_list flag is specified + * + * @param bool $flag + * @dataProvider isProductListDataProvider + */ + public function testIsProductList($flag) + { + $this->object->setData('is_product_list', $flag); + self::assertEquals($flag, $this->object->isProductList()); + } + + /** + * @return array + */ + public function isProductListDataProvider() + { + return [ + 'is_not_product_list' => [false], + 'is_product_list' => [true], + ]; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Pricing/Render/PriceBoxTest.php b/app/code/Magento/Catalog/Test/Unit/Pricing/Render/PriceBoxTest.php index 14dd4d8be0b5a..000827775058c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Pricing/Render/PriceBoxTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Pricing/Render/PriceBoxTest.php @@ -1,6 +1,6 @@ assertArrayHasKey($groupCode, $this->getModel()->modifyMeta($meta)); } + + public function testModifyMetaWithCaching() + { + $this->arrayManagerMock->expects($this->exactly(2)) + ->method('findPath') + ->willReturn(true); + $cacheManager = $this->getMockBuilder(CacheInterface::class) + ->getMockForAbstractClass(); + $cacheManager->expects($this->once()) + ->method('load') + ->with(Categories::CATEGORY_TREE_ID . '_'); + $cacheManager->expects($this->once()) + ->method('save'); + + $modifier = $this->createModel(); + $cacheContextProperty = new \ReflectionProperty( + Categories::class, + 'cacheManager' + ); + $cacheContextProperty->setAccessible(true); + $cacheContextProperty->setValue($modifier, $cacheManager); + + $groupCode = 'test_group_code'; + $meta = [ + $groupCode => [ + 'children' => [ + 'category_ids' => [ + 'sortOrder' => 10, + ], + ], + ], + ]; + $modifier->modifyMeta($meta); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php index c2b3de0c24cb0..248ca8b21a344 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php @@ -1,6 +1,6 @@ objectManager->getObject(\Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Images::class, [ + return $this->objectManager->getObject(Images::class, [ 'locator' => $this->locatorMock, ]); } public function testModifyData() { - $this->assertSame($this->getSampleData(), $this->getModel()->modifyData($this->getSampleData())); + $this->productMock->expects($this->once())->method('getId')->willReturn(2051); + $actualResult = $this->getModel()->modifyData($this->getSampleData()); + $this->assertSame('', $actualResult[2051]['product']['media_gallery']['images'][0]['label']); } public function testModifyMeta() { $meta = [ - \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Images::CODE_IMAGE_MANAGEMENT_GROUP => [ + Images::CODE_IMAGE_MANAGEMENT_GROUP => [ 'children' => [], 'label' => __('Images'), 'sortOrder' => '20', @@ -40,4 +42,24 @@ public function testModifyMeta() $this->assertSame([], $this->getModel()->modifyMeta($meta)); } + + /** + * {@inheritdoc} + */ + protected function getSampleData() + { + return [ + 2051 => [ + 'product' => [ + 'media_gallery' => [ + 'images' => [ + [ + 'label' => null + ] + ] + ] + ] + ] + ]; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/RelatedTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/RelatedTest.php index b0b2365c4f151..8bfcc0edd196e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/RelatedTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/RelatedTest.php @@ -1,6 +1,6 @@ arrayManager = $arrayManager; } + /** + * Retrieve cache interface + * + * @return CacheInterface + * @deprecated + */ + private function getCacheManager() + { + if (!$this->cacheManager) { + $this->cacheManager = ObjectManager::getInstance() + ->get(CacheInterface::class); + } + return $this->cacheManager; + } + /** * {@inheritdoc} */ @@ -254,8 +284,9 @@ protected function customizeCategoriesField(array $meta) */ protected function getCategoriesTree($filter = null) { - if (isset($this->categoriesTrees[$filter])) { - return $this->categoriesTrees[$filter]; + $categoryTree = $this->getCacheManager()->load(self::CATEGORY_TREE_ID . '_' . $filter); + if ($categoryTree) { + return unserialize($categoryTree); } $storeId = $this->locator->getStore()->getId(); @@ -307,9 +338,16 @@ protected function getCategoriesTree($filter = null) $categoryById[$category->getId()]['label'] = $category->getName(); $categoryById[$category->getParentId()]['optgroup'][] = &$categoryById[$category->getId()]; } + + $this->getCacheManager()->save( + serialize($categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']), + self::CATEGORY_TREE_ID . '_' . $filter, + [ + \Magento\Catalog\Model\Category::CACHE_TAG, + \Magento\Framework\App\Cache\Type\Block::CACHE_TAG + ] + ); - $this->categoriesTrees[$filter] = $categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']; - - return $this->categoriesTrees[$filter]; + return $categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']; } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php index d4103e20c5647..16002c9c01786 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php @@ -1,6 +1,6 @@ true, 'sortOrder' => $sortOrder, 'dataProvider' => static::CUSTOM_OPTIONS_LISTING, - 'links' => ['insertData' => '${ $.provider }:${ $.dataProvider }'], + 'imports' => ['insertData' => '${ $.provider }:${ $.dataProvider }'], ], ], ], @@ -478,7 +478,7 @@ protected function getImportOptionsModalConfig() 'render_url' => $this->urlBuilder->getUrl('mui/index/render'), 'realTimeLink' => true, 'behaviourType' => 'edit', - 'externalFilterMode' => true, + 'externalFilterMode' => false, 'currentProductId' => $this->locator->getProduct()->getId(), 'dataLinks' => [ 'imports' => false, diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 4fe12118dbfb3..176e578d7a73f 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -1,6 +1,6 @@ arrayManager->replace( $path, $data, - $this->formatNumber($this->arrayManager->get($path, $data)) + $this->formatWeight($this->arrayManager->get($path, $data)) ); } @@ -105,7 +101,7 @@ protected function customizeAdvancedPriceFormat(array $data) $value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE] = $this->formatPrice($value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE]); $value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE_QTY] = - $this->formatNumber((int)$value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE_QTY]); + (int)$value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE_QTY]; } } @@ -378,23 +374,6 @@ private function getLocaleCurrency() return $this->localeCurrency; } - /** - * The getter function to get the store manager for real application code - * - * @return \Magento\Store\Model\StoreManagerInterface - * - * @deprecated - */ - private function getStoreManager() - { - if ($this->storeManager === null) { - $this->storeManager = - \Magento\Framework\App\ObjectManager::getInstance()->get(StoreManagerInterface::class); - } - return $this->storeManager; - } - - /** * Format price according to the locale of the currency * @@ -407,7 +386,7 @@ protected function formatPrice($value) return null; } - $store = $this->getStoreManager()->getStore(); + $store = $this->locator->getStore(); $currency = $this->getLocaleCurrency()->getCurrency($store->getBaseCurrencyCode()); $value = $currency->toCurrency($value, ['display' => \Magento\Framework\Currency::NO_SYMBOL]); @@ -428,7 +407,7 @@ protected function formatNumber($value) $value = (float)$value; $precision = strlen(substr(strrchr($value, "."), 1)); - $store = $this->getStoreManager()->getStore(); + $store = $this->locator->getStore(); $currency = $this->getLocaleCurrency()->getCurrency($store->getBaseCurrencyCode()); $value = $currency->toCurrency($value, ['display' => \Magento\Framework\Currency::NO_SYMBOL, 'precision' => $precision]); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php index 810a06df4a42f..afa074aa93f98 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php @@ -1,6 +1,6 @@ locator->getProduct(); + $modelId = $product->getId(); + if ( + isset($data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery']['images']) + && is_array($data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery']['images']) + ) { + foreach ($data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery']['images'] as $index => $image) { + if (!isset($image['label'])) { + $data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery']['images'][$index]['label'] = ''; + } + } + } + return $data; } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php index 9c488cbebe11a..a9f14444a6b09 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/etc/adminhtml/di.xml b/app/code/Magento/Catalog/etc/adminhtml/di.xml index 0252314432971..1aff0dee34d32 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/di.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ @@ -47,6 +47,13 @@ + + + + option + + + Magento\Catalog\Model\Product\CopyConstructor\Composite @@ -66,7 +73,6 @@ - diff --git a/app/code/Magento/Catalog/etc/adminhtml/events.xml b/app/code/Magento/Catalog/etc/adminhtml/events.xml index a77e1e741a4be..034204feff5c9 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/events.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/adminhtml/menu.xml b/app/code/Magento/Catalog/etc/adminhtml/menu.xml index d0f15c930e6d2..ee0d1ec5c4117 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/menu.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/adminhtml/routes.xml b/app/code/Magento/Catalog/etc/adminhtml/routes.xml index 8dac88c2a22cd..5deeddb3bb4bd 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/routes.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/adminhtml/system.xml b/app/code/Magento/Catalog/etc/adminhtml/system.xml index 85949a953fc53..c5a1b3686fbe5 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/system.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/catalog_attributes.xml b/app/code/Magento/Catalog/etc/catalog_attributes.xml index d822d36eabfee..650652aa94555 100644 --- a/app/code/Magento/Catalog/etc/catalog_attributes.xml +++ b/app/code/Magento/Catalog/etc/catalog_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/catalog_attributes.xsd b/app/code/Magento/Catalog/etc/catalog_attributes.xsd index 00384d783eff1..d95d5a17c258e 100644 --- a/app/code/Magento/Catalog/etc/catalog_attributes.xsd +++ b/app/code/Magento/Catalog/etc/catalog_attributes.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/config.xml b/app/code/Magento/Catalog/etc/config.xml index a86b005be2857..4a8a523e0d55c 100644 --- a/app/code/Magento/Catalog/etc/config.xml +++ b/app/code/Magento/Catalog/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/crontab.xml b/app/code/Magento/Catalog/etc/crontab.xml index 2288ed4ebd8a8..d69ac8f319b5e 100644 --- a/app/code/Magento/Catalog/etc/crontab.xml +++ b/app/code/Magento/Catalog/etc/crontab.xml @@ -1,7 +1,7 @@ @@ -13,5 +13,8 @@ 0 0 * * * + + * * * * * + diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index b1f1d71bb9e57..075e33107d43b 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -1,7 +1,7 @@ @@ -16,6 +16,7 @@ + @@ -44,6 +45,7 @@ + @@ -615,7 +617,7 @@ - + Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE @@ -781,4 +783,26 @@ + + + + + Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderByBasePrice + Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderBySpecialPrice + Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderByTierPrice + Magento\Catalog\Model\ResourceModel\Product\Indexer\LinkedProductSelectBuilderByIndexPrice + + + + + + + + Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor + + + + + + diff --git a/app/code/Magento/Catalog/etc/eav_attributes.xml b/app/code/Magento/Catalog/etc/eav_attributes.xml index c480ea4dd2322..133849a28e048 100644 --- a/app/code/Magento/Catalog/etc/eav_attributes.xml +++ b/app/code/Magento/Catalog/etc/eav_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/events.xml b/app/code/Magento/Catalog/etc/events.xml index 544abf6b9e069..58cbe8d343bd6 100644 --- a/app/code/Magento/Catalog/etc/events.xml +++ b/app/code/Magento/Catalog/etc/events.xml @@ -1,7 +1,7 @@ @@ -51,4 +51,7 @@ + + + diff --git a/app/code/Magento/Catalog/etc/extension_attributes.xml b/app/code/Magento/Catalog/etc/extension_attributes.xml index 4b8e6ca708d7a..ca35211f82553 100644 --- a/app/code/Magento/Catalog/etc/extension_attributes.xml +++ b/app/code/Magento/Catalog/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/frontend/di.xml b/app/code/Magento/Catalog/etc/frontend/di.xml index 9b99bd4a78140..ca1e1e244f49c 100644 --- a/app/code/Magento/Catalog/etc/frontend/di.xml +++ b/app/code/Magento/Catalog/etc/frontend/di.xml @@ -1,7 +1,7 @@ @@ -18,9 +18,6 @@ Magento\Catalog\Model\ResourceModel\Category\Collection\FetchStrategy - - - true diff --git a/app/code/Magento/Catalog/etc/frontend/events.xml b/app/code/Magento/Catalog/etc/frontend/events.xml index 5ef8c72468314..dd225750f73be 100644 --- a/app/code/Magento/Catalog/etc/frontend/events.xml +++ b/app/code/Magento/Catalog/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/frontend/page_types.xml b/app/code/Magento/Catalog/etc/frontend/page_types.xml index 2557d79a1a49b..8f929046afeef 100644 --- a/app/code/Magento/Catalog/etc/frontend/page_types.xml +++ b/app/code/Magento/Catalog/etc/frontend/page_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/frontend/routes.xml b/app/code/Magento/Catalog/etc/frontend/routes.xml index 5adaf604c51d5..d4d52559673d6 100644 --- a/app/code/Magento/Catalog/etc/frontend/routes.xml +++ b/app/code/Magento/Catalog/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Catalog/etc/frontend/sections.xml b/app/code/Magento/Catalog/etc/frontend/sections.xml index 7c36594283640..0bc9c63494b33 100644 --- a/app/code/Magento/Catalog/etc/frontend/sections.xml +++ b/app/code/Magento/Catalog/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/indexer.xml b/app/code/Magento/Catalog/etc/indexer.xml index 88e6da345c393..5c2ca91e525d9 100644 --- a/app/code/Magento/Catalog/etc/indexer.xml +++ b/app/code/Magento/Catalog/etc/indexer.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml index 87e82543fc65b..ffbd5bb6b206d 100644 --- a/app/code/Magento/Catalog/etc/module.xml +++ b/app/code/Magento/Catalog/etc/module.xml @@ -1,12 +1,12 @@ - + diff --git a/app/code/Magento/Catalog/etc/mview.xml b/app/code/Magento/Catalog/etc/mview.xml index d6614e837dde3..4600bb7fad370 100644 --- a/app/code/Magento/Catalog/etc/mview.xml +++ b/app/code/Magento/Catalog/etc/mview.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/product_options.xml b/app/code/Magento/Catalog/etc/product_options.xml index 48d62d0c2c0ad..43bf4865cb49e 100644 --- a/app/code/Magento/Catalog/etc/product_options.xml +++ b/app/code/Magento/Catalog/etc/product_options.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/product_options.xsd b/app/code/Magento/Catalog/etc/product_options.xsd index a6bcb74ac2894..18b5934c1410f 100644 --- a/app/code/Magento/Catalog/etc/product_options.xsd +++ b/app/code/Magento/Catalog/etc/product_options.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/product_options_merged.xsd b/app/code/Magento/Catalog/etc/product_options_merged.xsd index 2a5951c57787d..7b9e6fa2650ec 100644 --- a/app/code/Magento/Catalog/etc/product_options_merged.xsd +++ b/app/code/Magento/Catalog/etc/product_options_merged.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/product_types.xml b/app/code/Magento/Catalog/etc/product_types.xml index a1516fee38ed5..513f0905b13ce 100644 --- a/app/code/Magento/Catalog/etc/product_types.xml +++ b/app/code/Magento/Catalog/etc/product_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/product_types.xsd b/app/code/Magento/Catalog/etc/product_types.xsd index e0cb33802851e..06999fbeddc7a 100644 --- a/app/code/Magento/Catalog/etc/product_types.xsd +++ b/app/code/Magento/Catalog/etc/product_types.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/product_types_base.xsd b/app/code/Magento/Catalog/etc/product_types_base.xsd index 94d8b87d167e3..eddd7a6845488 100644 --- a/app/code/Magento/Catalog/etc/product_types_base.xsd +++ b/app/code/Magento/Catalog/etc/product_types_base.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/product_types_merged.xsd b/app/code/Magento/Catalog/etc/product_types_merged.xsd index 1a1a9bfd8214c..1b1d92c163989 100644 --- a/app/code/Magento/Catalog/etc/product_types_merged.xsd +++ b/app/code/Magento/Catalog/etc/product_types_merged.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/view.xml b/app/code/Magento/Catalog/etc/view.xml index 756888e3b688f..8c7500d9c1374 100644 --- a/app/code/Magento/Catalog/etc/view.xml +++ b/app/code/Magento/Catalog/etc/view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index a8dc6ead7975f..de66084cb50ef 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/webapi_rest/di.xml b/app/code/Magento/Catalog/etc/webapi_rest/di.xml index 8606cd8de1136..67e74dfbfd44e 100644 --- a/app/code/Magento/Catalog/etc/webapi_rest/di.xml +++ b/app/code/Magento/Catalog/etc/webapi_rest/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/webapi_soap/di.xml b/app/code/Magento/Catalog/etc/webapi_soap/di.xml index 9d2f4abfa5b46..cb5273e4aeac5 100644 --- a/app/code/Magento/Catalog/etc/webapi_soap/di.xml +++ b/app/code/Magento/Catalog/etc/webapi_soap/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/etc/widget.xml b/app/code/Magento/Catalog/etc/widget.xml index e9907e5b17700..f54d4af816c09 100644 --- a/app/code/Magento/Catalog/etc/widget.xml +++ b/app/code/Magento/Catalog/etc/widget.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index 0745c98d7169a..4ff82a93b2914 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -700,6 +700,7 @@ Image,Image "Allowed file types: jpeg, gif, png.","Allowed file types: jpeg, gif, png." "Image Opacity","Image Opacity" "Example format: 200x300.","Example format: 200x300." +"This value does not follow the specified format (for example, 200x300).","This value does not follow the specified format (for example, 200x300)." "Image Position","Image Position" Small,Small "Attribute Label","Attribute Label" @@ -714,3 +715,4 @@ Disable,Disable none,none Overview,Overview Details,Details +"The value of Admin must be unique.", "The value of Admin must be unique." diff --git a/app/code/Magento/Catalog/registration.php b/app/code/Magento/Catalog/registration.php index 96b9df94d399e..fada27f08c173 100644 --- a/app/code/Magento/Catalog/registration.php +++ b/app/code/Magento/Catalog/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_CONFIGURE_ERROR.xml b/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_CONFIGURE_ERROR.xml index 2809386e4f94e..30add348f7d2b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_CONFIGURE_ERROR.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_CONFIGURE_ERROR.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_UPDATE_RESULT.xml b/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_UPDATE_RESULT.xml index a71dd55d3dfc0..ec97c79610237 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_UPDATE_RESULT.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/CATALOG_PRODUCT_COMPOSITE_UPDATE_RESULT.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_add.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_add.xml index 5f376149e96bf..d9c70ae487903 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_add.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_add.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_create.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_create.xml index 0a8b4e2509cd0..02734a674189e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_create.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_create.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_edit.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_edit.xml index 1f975b4a701a3..799c50dfc4756 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_edit.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_category_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_action_attribute_edit.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_action_attribute_edit.xml index be147a4270879..3a073f75eef12 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_action_attribute_edit.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_action_attribute_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertspricegrid.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertspricegrid.xml index 39b7f82b2e78d..0cd56d138149e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertspricegrid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertspricegrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertsstockgrid.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertsstockgrid.xml index 74e558c34cc79..d098da96d3e52 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertsstockgrid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_alertsstockgrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit.xml index ad6d9f5d4ef94..ddf02a7cdb9c2 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_form.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_form.xml index 59c5d5cff3158..8f4780d34b17d 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml index 5049f5ac8e3f5..a19d29a98720e 100755 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_change_attribute_set.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_change_attribute_set.xml index 82007f774971f..422cf537c3081 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_change_attribute_set.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_change_attribute_set.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssell.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssell.xml index 6f95ce72a20bf..9c1280a2500df 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssell.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssell.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssellgrid.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssellgrid.xml index 808e95a885616..96c66485f2132 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssellgrid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_crosssellgrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_customoptions.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_customoptions.xml index 064463bd0d613..39781cc8adcf0 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_customoptions.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_customoptions.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_edit.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_edit.xml index d8b0ce7c957e0..3375f5b8233f5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_edit.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_form.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_form.xml index bdcd5da65bbea..194c745e6a65a 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_grid.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_grid.xml index 7343969a40ba4..e214ccad3dc21 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_grid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_index.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_index.xml index 7ee21e218051f..bad6a5d165535 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_index.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_new.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_new.xml index 0d6dae0c99a87..cb993bc892eac 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_new.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_options.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_options.xml index e52d7e7ec1a14..7d88ff2a04384 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_options.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_options.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_optionsimportgrid.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_optionsimportgrid.xml index 699b6084c314a..7f6f62943bbea 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_optionsimportgrid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_optionsimportgrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_related.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_related.xml index e1f2eb0403580..6b688eeec2084 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_related.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_related.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_relatedgrid.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_relatedgrid.xml index 8d2fb11dc18c1..4a306dd725b91 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_relatedgrid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_relatedgrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_reload.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_reload.xml index 82007f774971f..422cf537c3081 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_reload.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_reload.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml index 1dc0de6498cb1..bbbc1e21669e1 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_edit.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_edit.xml index 1c7ae6de66ed0..bd8c2cd3550f3 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_edit.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_index.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_index.xml index 23b859d526e10..b25eecbbc2502 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_index.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_set_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsell.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsell.xml index f7ec295f154a0..ce0b1521d82e6 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsell.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsell.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsellgrid.xml b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsellgrid.xml index 097649c8c0aa3..83c19659b5135 100644 --- a/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsellgrid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/layout/catalog_product_upsellgrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/requirejs-config.js b/app/code/Magento/Catalog/view/adminhtml/requirejs-config.js index d2e45cbfb42ee..848d1f1da908c 100644 --- a/app/code/Magento/Catalog/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/Catalog/view/adminhtml/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -17,4 +17,4 @@ var config = { deps: [ 'Magento_Catalog/catalog/product' ] -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml index b1f8197650fd9..eaeed5b12ebaf 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml @@ -1,6 +1,6 @@ getStoresSortedBySortOrder(); ?>
- + + escapeHtml(__('Manage Options (Values of Your Attribute)'))?> +
- + - getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> class="_required"> - getName()) ?> + getStoresSortedBySortOrder(); - - @@ -54,23 +64,48 @@ $stores = $block->getStoresSortedBySortOrder(); - + @@ -90,6 +125,10 @@ $stores = $block->getStoresSortedBySortOrder(); "attributesData": , "isSortable": getReadOnly() && !$block->canManageOptionDefaultOnly()) ?>, "isReadOnly": getReadOnly(); ?> + }, + "Magento_Catalog/catalog/product/attribute/unique-validate": { + "element": "required-dropdown-attribute-unique", + "message": "escapeHtml(__('The value of Admin must be unique.')) ?>" } } } diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml index ceebeea705ec7..3f51c30056e98 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml @@ -1,6 +1,6 @@ ').attr('id', 'messages'); + jQuery('.page-main-actions').after(block); } TreePanels.rebuildTrees(); if(!jQuery('#set-prop-form').valid()) { diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main/tree/attribute.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main/tree/attribute.phtml index 526d2f98ead9c..2928eff384df6 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main/tree/attribute.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main/tree/attribute.phtml @@ -1,5 +1,5 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/add.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/add.phtml index 536e840249b78..cf40ee6d78af6 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/add.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/add.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/main.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/main.phtml index 3b5748da54823..2cdb9f451a86f 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/main.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/toolbar/main.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml index bebc0b0a1b699..6eed355cc3b83 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/date.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml index 5d35a9e8be152..cb60254d4d8c7 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml index 5ffacc462ac83..82d2111b986cd 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/wysiwyg/js.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml index 965694d7f94c4..25eb8092ab40d 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml @@ -1,7 +1,7 @@ @@ -13,6 +13,7 @@ crosssell_product_listing.crosssell_product_listing_data_sourceproduct_columns + Magento_Catalog::products diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml index dc8ced173bc54..28522ca5c2ba2 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml @@ -1,7 +1,7 @@ @@ -55,12 +55,13 @@ + Magento_Catalog/component/image-size-field Image Size text input watermark_image_size - true + true Example format: 200x300. @@ -118,12 +119,13 @@ + Magento_Catalog/component/image-size-field Image Size text input watermark_thumbnail_size - true + true Example format: 200x300. @@ -181,12 +183,13 @@ + Magento_Catalog/component/image-size-field Image Size text input watermark_small_image_size - true + true Example format: 200x300. diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/new_category_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/new_category_form.xml index dbe6aa9eb7d91..a0307886770c6 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/new_category_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/new_category_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml index 870304c881627..ab5ab6e288e13 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml index 4067cd062de6c..24243f35bc958 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ product_attributes_grid.product_attributes_grid_data_source product_attributes_columns + Magento_Catalog::products diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml index 5c7292637129d..beef5bfe6c314 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ product_custom_options_listing.product_custom_options_listing_data_source product_columns + Magento_Catalog::products diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_form.xml index 2db3d337822b6..b99e01147c00d 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml index ec88952af5033..f3285ba03962b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ product_listing.product_listing_data_source product_columns + Magento_Catalog::products diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml index 25350158c5297..7801b4169a7e2 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ related_product_listing.related_product_listing_data_source product_columns + Magento_Catalog::products diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml index fc03f128f4617..2cca1d18b46f5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ upsell_product_listing.upsell_product_listing_data_source product_columns + Magento_Catalog::products diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/apply-to-type-switcher.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/apply-to-type-switcher.js index 595638d8ca6ef..13543ade8f726 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/apply-to-type-switcher.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/apply-to-type-switcher.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js index 9c0d986c7e9f2..4ba2d110ffb34 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global alert:true*/ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/assign-products.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/assign-products.js index ad5f52095f36b..1da9c2c379c37 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/assign-products.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/assign-products.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/edit.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/edit.js index 28bc0734ef033..66eb039790f28 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/edit.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/edit.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** @@ -75,4 +75,4 @@ define([ categorySubmit(config.url, config.ajax); }); }; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/form.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/form.js index f64111a2f0ef8..9f413832537e2 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/form.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/category/form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product-attributes.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product-attributes.js index 937c83c14faa4..4df5af1fba8e8 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product-attributes.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product-attributes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 7ca4b6d607476..b751e75947ecc 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ require([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/attribute/unique-validate.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/attribute/unique-validate.js new file mode 100644 index 0000000000000..2af880f4d04c5 --- /dev/null +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/attribute/unique-validate.js @@ -0,0 +1,46 @@ +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mage/backend/validation' +], function (jQuery) { + 'use strict'; + + return function (config) { + var _config = jQuery.extend({ + element: null, + message: '', + uniqueClass: 'required-unique' + }, config); + + if (typeof _config.element === 'string') { + jQuery.validator.addMethod( + _config.element, + + function (value, element) { + var inputs = jQuery(element) + .closest('table') + .find('.' + _config.uniqueClass + ':visible'), + valuesHash = {}, + isValid = true; + + inputs.each(function (el) { + var inputValue = inputs[el].value; + + if (typeof valuesHash[inputValue] !== 'undefined') { + isValid = false; + } + valuesHash[inputValue] = el; + }); + + return isValid; + }, + + _config.message + ); + } + }; +}); diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js index 28bcd7011ab8f..0f45dda8043d0 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/type-events.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/type-events.js index 55a4599ce85e5..9de0ff75fa843 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/type-events.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/type-events.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/file-type-field.js b/app/code/Magento/Catalog/view/adminhtml/web/component/file-type-field.js index 491d765740b0b..bed32eb574695 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/component/file-type-field.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/file-type-field.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js b/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js new file mode 100644 index 0000000000000..db4fe46a3515e --- /dev/null +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js @@ -0,0 +1,42 @@ +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'Magento_Ui/js/lib/validation/utils', + 'Magento_Ui/js/form/element/abstract', + 'Magento_Ui/js/lib/validation/validator' +], function ($, utils, Abstract, validator) { + 'use strict'; + + validator.addRule( + 'validate-image-size-range', + function (value) { + var dataAttrRange = /^(\d+)[Xx](\d+)$/, + m; + + if (utils.isEmptyNoTrim(value)) { + return true; + } + + m = dataAttrRange.exec(value); + + return !!(m && m[1] > 0 && m[2] > 0); + }, + $.mage.__('This value does not follow the specified format (for example, 200x300).') + ); + + return Abstract.extend({ + + /** + * Checks for relevant value + * + * @returns {Boolean} + */ + isRangeCorrect: function () { + return validator('validate-image-size-range', this.value()).passed; + } + }); +}); diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/select-type-grid.js b/app/code/Magento/Catalog/view/adminhtml/web/component/select-type-grid.js index ba5307da4cda1..57d35424268b8 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/component/select-type-grid.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/select-type-grid.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-container.js b/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-container.js index 5105271769d71..b3ef035402c3e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-container.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-container.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-input.js b/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-input.js index 694eb0163467c..d520758d456a5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-input.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-input.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-select.js b/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-select.js index 555024e026a0b..6b61b5e49c97a 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-select.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/static-type-select.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/text-type-field.js b/app/code/Magento/Catalog/view/adminhtml/web/component/text-type-field.js index d09110f41d3cf..72d97b7aebcd9 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/component/text-type-field.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/text-type-field.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/bundle-proxy-button.js b/app/code/Magento/Catalog/view/adminhtml/web/js/bundle-proxy-button.js index 60141a7138008..42543656f210b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/bundle-proxy-button.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/bundle-proxy-button.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/category-tree.js b/app/code/Magento/Catalog/view/adminhtml/web/js/category-tree.js index 0cb4932a012f3..5453b760e2f31 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/category-tree.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/category-tree.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ @@ -94,4 +94,4 @@ define([ }); return $.mage.categoryTree; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attribute-set-select.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attribute-set-select.js index 3fa5d6a6790f3..baefa1ae2e4b5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attribute-set-select.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attribute-set-select.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-fieldset.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-fieldset.js index 8b2d64353f72f..1e363ef2a1a0f 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-fieldset.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-fieldset.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-grid-paging.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-grid-paging.js index f698de4a5386f..641dfaf295150 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-grid-paging.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-grid-paging.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-insert-listing.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-insert-listing.js index 5d9234b76d544..10be9f2ffc907 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-insert-listing.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/attributes-insert-listing.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/checkbox.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/checkbox.js index 944ef4f7b4d5f..b371efca26f64 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/checkbox.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/checkbox.js @@ -1,4 +1,4 @@ -/* Copyright © 2016 Magento. All rights reserved. +/* Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-hide-select.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-hide-select.js index fd36504b5a77c..4bf54406e3598 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-hide-select.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-hide-select.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/input.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/input.js index 4dd196da99294..1961bc5fde625 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/input.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/input.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/select.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/select.js index ad6090cdd8e46..2dc21fc11cf55 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/select.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/select.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/strategy.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/strategy.js index 6a31b28df2c05..e8b276c171ca4 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/strategy.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/strategy.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define(function () { diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/yesno.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/yesno.js index 3c40951499fff..7362acbe63eb2 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/yesno.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/disable-on-option/yesno.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js index 0dea377e5d84b..42306d7b8799e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-import-custom-options.js @@ -1,61 +1,84 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ - 'Magento_Ui/js/dynamic-rows/dynamic-rows', + 'Magento_Ui/js/dynamic-rows/dynamic-rows-grid', + 'underscore', 'mageUtils' -], function (DynamicRows, utils) { +], function (DynamicRows, _, utils) { 'use strict'; + var maxId = 0, + + /** + * Stores max option_id value of the options from recordData once on initialization + * @param {Array} data - array with records data + */ + initMaxId = function (data) { + if (data && data.length) { + maxId = _.max(data, function (record) { + return parseInt(record['option_id'], 10) || 0; + })['option_id']; + maxId = parseInt(maxId, 10) || 0; + } + }; + return DynamicRows.extend({ defaults: { - dataProvider: '', - insertData: [], - listens: { - 'insertData': 'processingInsertData' - } + mappingSettings: { + enabled: false, + distinct: false + }, + update: true, + map: { + 'option_id': 'option_id' + }, + identificationProperty: 'option_id', + identificationDRProperty: 'option_id' }, - /** - * Calls 'initObservable' of parent - * - * @returns {Object} Chainable. - */ - initObservable: function () { - this._super() - .observe([ - 'insertData' - ]); + /** @inheritdoc */ + initialize: function () { + this._super(); + initMaxId(this.recordData()); return this; }, - /** - * Parsed data - * - * @param {Array} data - array with data - * about selected records - */ + /** @inheritdoc */ processingInsertData: function (data) { - if (!data.length) { - return false; - } + var options = [], + currentOption; - data.each(function (options) { - options.options.each(function (option) { - var path = this.dataScope + '.' + this.index + '.' + this.recordIterator, - curOption = utils.copy(option); + if (!data) { + return; + } + data.each(function (item) { + if (!item.options) { + return; + } + item.options.each(function (option) { + currentOption = utils.copy(option); - if (curOption.hasOwnProperty('sort_order')) { - delete curOption['sort_order']; + if (currentOption.hasOwnProperty('sort_order')) { + delete currentOption['sort_order']; } + currentOption['option_id'] = ++maxId; + options.push(currentOption); + }); + }); - this.source.set(path, curOption); - this.addChild(curOption, false); - }, this); + if (!options.length) { + return; + } + this.cacheGridData = options; + options.each(function (opt) { + this.mappingValue(opt); }, this); + + this.insertData([]); }, /** @@ -63,6 +86,27 @@ define([ */ clearDataProvider: function () { this.source.set(this.dataProvider, []); + }, + + /** @inheritdoc */ + processingAddChild: function (ctx, index, prop) { + if (ctx && !_.isNumber(ctx['option_id'])) { + ctx['option_id'] = ++maxId; + } else if (!ctx) { + this.showSpinner(true); + this.addChild(ctx, index, prop); + + return; + } + + this._super(ctx, index, prop); + }, + + /** + * Mutes parent method + */ + updateInsertData: function () { + return false; } }); }); diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js index fd69874c318e2..3d3c30e4797ae 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/input-handle-required.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/input-handle-required.js index 9d2154656b005..c342e961fa9e2 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/input-handle-required.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/input-handle-required.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/messages.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/messages.js index 78956749be6a9..7e3696ba24bf8 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/messages.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/messages.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/multiselect-handle-required.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/multiselect-handle-required.js index 3e26f693456c4..b7146137c6bb3 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/multiselect-handle-required.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/multiselect-handle-required.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-form.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-form.js index 96d3f0accec5a..360349f8c61e5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-form.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-insert-form.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-insert-form.js index 4c646b1de8e2f..f3624de9cbd0f 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-insert-form.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-attribute-insert-form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-category.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-category.js index 8037d1c6ac3f4..7a16067b37291 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-category.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/new-category.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/product-status.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/product-status.js index c02af7c6369b2..3e3c811584973 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/product-status.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/product-status.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-handle-required.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-handle-required.js index dc7b4dee30b1b..08ed325c82a78 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-handle-required.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-handle-required.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-to-checkbox.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-to-checkbox.js index 4232c54e7b617..281ef42a9e533 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-to-checkbox.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/select-to-checkbox.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/url-key-handle-changes.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/url-key-handle-changes.js index 2305a79fa7e73..b12f73c17125a 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/url-key-handle-changes.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/url-key-handle-changes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/date.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/date.js index 1f1aa3a4a5d4d..ecdb3a66006b7 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/date.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/date.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/fieldset.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/fieldset.js index 2ddd6566cb074..581153832d3a5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/fieldset.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/fieldset.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/input.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/input.js index 950ab4aa4eb34..bd832632f7513 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/input.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/input.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/select.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/select.js index c63e79316b3ec..05453dc19bff8 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/select.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/select.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/strategy.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/strategy.js index 7d1f0557108f5..2e59efeab1b58 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/strategy.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/strategy.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define(function () { diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/textarea.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/textarea.js index 0c0860e1b7102..7446174982a21 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/textarea.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/textarea.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/yesno.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/yesno.js index 5f64db1ee6dd2..9f8a9e43dacc5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/yesno.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/visible-on-option/yesno.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options-type.js b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options-type.js index e4c65f543eddf..878e8e1429680 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options-type.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options-type.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js index 9de11667b9d56..0611c4fae9233 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true*/ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/edit-tree.js b/app/code/Magento/Catalog/view/adminhtml/web/js/edit-tree.js index 9d84efd42c7d9..7420595078071 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/edit-tree.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/edit-tree.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/action-delete.js b/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/action-delete.js index d809ecc74fa4b..1ecfddac7abb8 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/action-delete.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/action-delete.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/checkbox.js b/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/checkbox.js index cffa4dff8952b..57d45551d180b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/checkbox.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/checkbox.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/input.js b/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/input.js index 688dc39692dac..84be3a4f8783b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/input.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/form/element/input.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/new-category-dialog.js b/app/code/Magento/Catalog/view/adminhtml/web/js/new-category-dialog.js index 41c29880de8c9..e20d3f3e0c5b1 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/new-category-dialog.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/new-category-dialog.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js index b366f61ba4994..75d768dae7bb6 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js b/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js index eba8ef201eae2..2cfde92d6a762 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint jquery:true*/ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js b/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js index 176cc9bd5c80c..a2ae5b794f601 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/product/weight-handler.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/attributes/grid/paging.html b/app/code/Magento/Catalog/view/adminhtml/web/template/attributes/grid/paging.html index 6ad88dd64d9e3..bf03ffb1049e7 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/attributes/grid/paging.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/attributes/grid/paging.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/checkbox.html b/app/code/Magento/Catalog/view/adminhtml/web/template/checkbox.html index 9b737a457f3f5..7a2c8e42364df 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/checkbox.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/checkbox.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/action-delete.html b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/action-delete.html index 9f223325939fb..3a516ad41358f 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/action-delete.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/action-delete.html @@ -1,6 +1,6 @@ @@ -13,4 +13,4 @@ } "> - \ No newline at end of file + diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-service.html b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-service.html index 9b1a3936b9f43..ad83bc144615e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-service.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/helper/custom-option-service.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html index 70b1b6033f7f6..560bc90ea6d19 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/form/element/input.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html index fa8a4fec7cc78..cb741f5288d28 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/base/layout/catalog_product_prices.xml b/app/code/Magento/Catalog/view/base/layout/catalog_product_prices.xml index aeb647660af7c..b47a6a3e69d86 100644 --- a/app/code/Magento/Catalog/view/base/layout/catalog_product_prices.xml +++ b/app/code/Magento/Catalog/view/base/layout/catalog_product_prices.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/base/layout/default.xml b/app/code/Magento/Catalog/view/base/layout/default.xml index 25a23d2be7df4..776dbc4b646ef 100644 --- a/app/code/Magento/Catalog/view/base/layout/default.xml +++ b/app/code/Magento/Catalog/view/base/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/base/layout/empty.xml b/app/code/Magento/Catalog/view/base/layout/empty.xml index 25a23d2be7df4..776dbc4b646ef 100644 --- a/app/code/Magento/Catalog/view/base/layout/empty.xml +++ b/app/code/Magento/Catalog/view/base/layout/empty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/base/templates/js/components.phtml b/app/code/Magento/Catalog/view/base/templates/js/components.phtml index e490a6aa04923..bdcb2e9bf7747 100644 --- a/app/code/Magento/Catalog/view/base/templates/js/components.phtml +++ b/app/code/Magento/Catalog/view/base/templates/js/components.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/base/templates/product/price/default.phtml b/app/code/Magento/Catalog/view/base/templates/product/price/default.phtml index a72cbcf8e8981..01d82db69d2ce 100644 --- a/app/code/Magento/Catalog/view/base/templates/product/price/default.phtml +++ b/app/code/Magento/Catalog/view/base/templates/product/price/default.phtml @@ -1,6 +1,6 @@ @@ -21,6 +21,11 @@ + + + diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default.xml index a9cfdf8f834bd..d6788f3d4eed6 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default_without_children.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default_without_children.xml index 7509438df2553..e01b48cc71b11 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default_without_children.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_category_view_type_default_without_children.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_compare_index.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_compare_index.xml index 3e16064e57312..c6f02a8acb155 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_compare_index.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_compare_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_gallery.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_gallery.xml index 837d34157a600..7e39fd35d6cde 100755 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_gallery.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_gallery.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_opengraph.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_opengraph.xml index 6bb8a78949038..661ec52df3dcd 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_opengraph.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_opengraph.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml index dd23502c49c86..a69fd034568b3 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml @@ -1,7 +1,7 @@ @@ -82,7 +82,10 @@ - + + + @@ -129,11 +132,21 @@ related + + + upsell + + + diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_simple.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_simple.xml index bc1959a36cb72..6703d18deac37 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_simple.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_simple.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_virtual.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_virtual.xml index 6155df2f60653..dd93e8064e60c 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_virtual.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view_type_virtual.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/checkout_cart_item_renderers.xml b/app/code/Magento/Catalog/view/frontend/layout/checkout_cart_item_renderers.xml index 2ad9ebb874ea2..ee16e638b64cb 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/checkout_cart_item_renderers.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/checkout_cart_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/layout/default.xml b/app/code/Magento/Catalog/view/frontend/layout/default.xml index ab424810401c9..f267c2a5ae634 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/default.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Catalog/view/frontend/requirejs-config.js b/app/code/Magento/Catalog/view/frontend/requirejs-config.js index c0d05a322b7cd..790c25ee6dce2 100644 --- a/app/code/Magento/Catalog/view/frontend/requirejs-config.js +++ b/app/code/Magento/Catalog/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Catalog/view/frontend/templates/category/cms.phtml b/app/code/Magento/Catalog/view/frontend/templates/category/cms.phtml index 06d1fc56b6f4b..818456d2272f6 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/category/cms.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/category/cms.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml index f78631f32a80a..c3280c563fe58 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml index 324bc105adc72..e40c47e1a8361 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml @@ -1,6 +1,6 @@ helper('Magento\Catalog\Helper\Output');
> - helper('Magento\Wishlist\Helper\Data')->isAllow()): ?> - - - + getChildBlock('addto')): ?> + setProduct($_product)->getChildHtml(); ?> - helper('Magento\Catalog\Helper\Product\Compare'); - ?> - - -
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/addto/compare.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/addto/compare.phtml new file mode 100644 index 0000000000000..518944dfb236c --- /dev/null +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/addto/compare.phtml @@ -0,0 +1,17 @@ + + + + diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml index ab5702770354b..db299487d17d8 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml @@ -1,6 +1,6 @@ getType()) { $shuffle = (int) $block->isShuffled(); $canItemsAddToCart = $block->canItemsAddToCart(); - $showWishlist = true; - $showCompare = true; + $showAddTo = true; $showCart = false; $templateType = null; $description = false; @@ -45,8 +44,7 @@ switch ($type = $block->getType()) { $shuffle = 0; $canItemsAddToCart = $block->canItemsAddToCart(); - $showWishlist = true; - $showCompare = true; + $showAddTo = true; $showCart = false; $templateType = null; $description = false; @@ -64,8 +62,7 @@ switch ($type = $block->getType()) { $limit = $block->getPositionLimit(); $shuffle = (int) $block->isShuffled(); - $showWishlist = false; - $showCompare = false; + $showAddTo = false; $showCart = false; $templateType = null; $description = false; @@ -85,8 +82,7 @@ switch ($type = $block->getType()) { $limit = $block->getItemLimit('upsell'); $shuffle = 0; - $showWishlist = false; - $showCompare = false; + $showAddTo = false; $showCart = false; $templateType = null; $description = false; @@ -104,8 +100,7 @@ switch ($type = $block->getType()) { $title = __('More Choices:'); $items = $block->getItemCollection(); - $showWishlist = true; - $showCompare = true; + $showAddTo = true; $showCart = true; $templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::SHORT_VIEW; $description = false; @@ -123,8 +118,7 @@ switch ($type = $block->getType()) { $title = __('More Choices:'); $items = $block->getItems(); - $showWishlist = true; - $showCompare = true; + $showAddTo = true; $showCart = true; $templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::SHORT_VIEW; $description = false; @@ -144,8 +138,7 @@ switch ($type = $block->getType()) { $title = __('New Products'); $items = $exist; - $showWishlist = true; - $showCompare = true; + $showAddTo = true; $showCart = true; $templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::SHORT_VIEW; $description = ($mode == 'list') ? true : false; @@ -219,7 +212,7 @@ switch ($type = $block->getType()) { - +
@@ -248,23 +241,10 @@ switch ($type = $block->getType()) {
- + diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml index 7feb2b077dea9..89386162ae855 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml @@ -1,6 +1,6 @@ -getProduct(); -$_wishlistSubmitParams = $this->helper('Magento\Wishlist\Helper\Data')->getAddParams($_product); -$compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare'); -?> - - diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml new file mode 100644 index 0000000000000..512b91015d7a8 --- /dev/null +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto/compare.phtml @@ -0,0 +1,14 @@ + + + diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml index c9680034e1e21..72ddb305e2c4b 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml @@ -1,6 +1,6 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml index eae8197f7231f..cb99796f6617e 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/attribute.phtml @@ -1,6 +1,6 @@ require([ 'jquery', - 'Magento_Catalog/js/price-box' + 'priceBox' ], function($){ - var priceBoxes = $('[data-role=priceBox]'); + var dataPriceBoxSelector = '[data-role=priceBox]', + dataProductIdSelector = '[data-product-id=escapeHtml($_product->getId())?>]', + priceBoxes = $(dataPriceBoxSelector + dataProductIdSelector); priceBoxes = priceBoxes.filter(function(index, elem){ return !$(elem).find('.price-from').length; diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 600902bec5d19..c5e9fc9f6044f 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -1,6 +1,6 @@ decorateArray($block->getOptions()) ?> +getProduct()->getId() ?> \ No newline at end of file + diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml index cd7e526403835..b2b17958f7c83 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ configurable_associated_product_listing.data_source product_columns + Magento_Catalog::products diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml index fd7759725e4bc..86ff3cbd46033 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ product_attributes_listing.product_attributes_listing_data_source product_attributes_columns + Magento_Catalog::products diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_form.xml b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_form.xml index 2896efca648e6..a928988a29cd9 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_form.xml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/css/configurable-product.css b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/css/configurable-product.css index 88a8e3876832a..30d75898e79bc 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/css/configurable-product.css +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/css/configurable-product.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js index ecc960bdb9ea5..98461addf4c4f 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/container-configurable-handler.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/container-configurable-handler.js index 542a9e492d586..e3834bc3464c1 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/container-configurable-handler.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/container-configurable-handler.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-price-type.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-price-type.js index 107fa05af1d3d..99a495a509179 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-price-type.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-price-type.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-warning.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-warning.js index 3c0b5b82633cc..210361945c541 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-warning.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/custom-options-warning.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js index ffabd9a8627df..7f02df57d48e5 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -391,11 +391,11 @@ define([ 'small_image': row['small_image'], image: row.image, 'thumbnail': row.thumbnail, - 'attributes': attributesText + 'attributes': attributesText, + 'was_changed': true }; product[this.canEditField] = row.editable; product[this.newProductField] = row.newProduct; - tmpArray.push(product); }, this); diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/file-uploader.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/file-uploader.js index 37f183197dae0..a90d977da6056 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/file-uploader.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/file-uploader.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/modal-configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/modal-configurable.js index 81f1387eb4f46..b0dfe14fe9d6b 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/modal-configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/modal-configurable.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable-type-handler.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable-type-handler.js index ed881be011d7f..857dd8cfa38e8 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable-type-handler.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable-type-handler.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js index 988f5f963e2fb..df3b1638f61d1 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /**************************** CONFIGURABLE PRODUCT **************************/ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/options/price-type-handler.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/options/price-type-handler.js index 4a9edda0eb496..cd354741bb061 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/options/price-type-handler.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/options/price-type-handler.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /* @@ -80,4 +80,4 @@ define([ } }; }); -*/ \ No newline at end of file +*/ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/paging/sizes.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/paging/sizes.js new file mode 100644 index 0000000000000..386c486cea7b7 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/paging/sizes.js @@ -0,0 +1,29 @@ +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'Magento_Ui/js/grid/paging/sizes' +], function (Sizes) { + 'use strict'; + + return Sizes.extend({ + defaults: { + excludedOptions: ['100', '200'] + }, + + /** + * @override + */ + initialize: function () { + this._super(); + + this.excludedOptions.forEach(function (excludedOption) { + delete this.options[excludedOption]; + }, this); + this.updateArray(); + + return this; + } + }); +}); diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/product-grid.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/product-grid.js index 4d1867669ade0..d9aa420b6106b 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/product-grid.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/product-grid.js @@ -1,6 +1,6 @@ // jscs:disable requireDotNotation /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/attributes_values.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/attributes_values.js index e16ea059c2b1f..c3c4bc2336a1b 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/attributes_values.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/attributes_values.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ // jscs:disable jsDoc diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js index f6769b0d0a9f9..ae4a51fb3b0bd 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/select_attributes.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/select_attributes.js index 3653e91894c29..961e2ca23ed36 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/select_attributes.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/select_attributes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ // jscs:disable jsDoc diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js index de2c7aa1db53f..1d504cda1738b 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ // jscs:disable jsDoc @@ -8,8 +8,9 @@ define([ 'jquery', 'ko', 'underscore', + 'Magento_Ui/js/grid/paging/paging', 'mage/translate' -], function (Component, $, ko, _) { +], function (Component, $, ko, _, paging) { 'use strict'; return Component.extend({ @@ -25,22 +26,61 @@ define([ gridExisting: [], gridNew: [], gridDeleted: [], + variationsExisting: [], + variationsNew: [], + variationsDeleted: [], + pagingExisting: paging({ + name: 'configurableWizard.pagingExisting', + sizesConfig: { + component: 'Magento_ConfigurableProduct/js/variations/paging/sizes', + name: 'configurableWizard.pagingExisting_sizes' + } + }), + pagingNew: paging({ + name: 'configurableWizard.pagingNew', + sizesConfig: { + component: 'Magento_ConfigurableProduct/js/variations/paging/sizes', + name: 'configurableWizard.pagingNew_sizes' + } + }), + pagingDeleted: paging({ + name: 'configurableWizard.pagingDeleted', + sizesConfig: { + component: 'Magento_ConfigurableProduct/js/variations/paging/sizes', + name: 'configurableWizard.pagingDeleted_sizes' + } + }), attributes: [], attributesName: [$.mage.__('Images'), $.mage.__('SKU'), $.mage.__('Quantity'), $.mage.__('Price')], sections: [], gridTemplate: 'Magento_ConfigurableProduct/variations/steps/summary-grid' }, initObservable: function () { + var pagingObservables = { + currentNew: ko.getObservable(this.pagingNew, 'current'), + currentExisting: ko.getObservable(this.pagingExisting, 'current'), + currentDeleted: ko.getObservable(this.pagingDeleted, 'current'), + pageSizeNew: ko.getObservable(this.pagingNew, 'pageSize'), + pageSizeExisting: ko.getObservable(this.pagingExisting, 'pageSize'), + pageSizeDeleted: ko.getObservable(this.pagingDeleted, 'pageSize') + }; + this._super().observe('gridExisting gridNew gridDeleted attributes sections'); this.gridExisting.columns = ko.observableArray(); this.gridNew.columns = ko.observableArray(); this.gridDeleted.columns = ko.observableArray(); + _.each(pagingObservables, function (observable) { + observable.subscribe(function () { + this.generateGrid(); + }, this); + }, this); + return this; }, nextLabelText: $.mage.__('Generate Products'), variations: [], - generateGrid: function (variations, getSectionValue) { + calculate: function (variations, getSectionValue) { var productSku = this.variationsComponent().getProductValue('sku'), productPrice = this.variationsComponent().getProductPrice(), productWeight = this.variationsComponent().getProductValue('weight'), @@ -48,8 +88,8 @@ define([ gridExisting = [], gridNew = [], gridDeleted = []; - this.variations = []; + this.variations = []; _.each(variations, function (options) { var product, images, sku, quantity, price, variation, productId = this.variationsComponent().getProductIdByOptions(options); @@ -101,14 +141,6 @@ define([ variationsKeys.push(this.variationsComponent().getVariationKey(options)); }, this); - this.gridExisting(gridExisting); - this.gridExisting.columns(this.getColumnsName(this.wizard.data.attributes)); - - if (gridNew.length > 0) { - this.gridNew(gridNew); - this.gridNew.columns(this.getColumnsName(this.wizard.data.attributes)); - } - _.each(_.omit(this.variationsComponent().productAttributesMap, variationsKeys), function (productId) { gridDeleted.push(this.prepareRowForGrid( _.findWhere(this.variationsComponent().variations, { @@ -117,13 +149,28 @@ define([ )); }.bind(this)); - if (gridDeleted.length > 0) { - this.gridDeleted(gridDeleted); - this.gridDeleted.columns(this.getColumnsName(this.variationsComponent().productAttributes)); - } + this.variationsExisting = gridExisting; + this.variationsNew = gridNew; + this.variationsDeleted = gridDeleted; + + }, + generateGrid: function () { + var pageExisting = this.pagingExisting.pageSize * this.pagingExisting.current, + pageNew = this.pagingNew.pageSize * this.pagingNew.current, + pageDeleted = this.pagingDeleted.pageSize * this.pagingDeleted.current; + + this.pagingExisting.totalRecords = this.variationsExisting.length; + this.gridExisting(this.variationsExisting.slice(pageExisting - this.pagingExisting.pageSize, pageExisting)); + + this.pagingNew.totalRecords = this.variationsNew.length; + this.gridNew(this.variationsNew.slice(pageNew - this.pagingNew.pageSize, pageNew)); + + this.pagingDeleted.totalRecords = this.variationsDeleted.length; + this.gridDeleted(this.variationsDeleted.slice(pageDeleted - this.pagingDeleted.pageSize, pageDeleted)); }, prepareRowForGrid: function (variation) { var row = []; + row.push(_.extend({ images: [] }, variation.images)); @@ -158,7 +205,11 @@ define([ this.gridNew([]); this.gridExisting([]); this.gridDeleted([]); - this.generateGrid(wizard.data.variations, wizard.data.sectionHelper); + this.gridExisting.columns(this.getColumnsName(this.wizard.data.attributes)); + this.gridNew.columns(this.getColumnsName(this.wizard.data.attributes)); + this.gridDeleted.columns(this.getColumnsName(this.variationsComponent().productAttributes)); + this.calculate(wizard.data.variations, wizard.data.sectionHelper); + this.generateGrid(); }, force: function () { this.variationsComponent().render(this.variations, this.attributes()); diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js index 6b160c7624265..cbcf2129aa542 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js @@ -1,6 +1,6 @@ // jscs:disable requireDotNotation /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ // jscs:disable jsDoc @@ -301,6 +301,12 @@ define([ * Chose action for the form save button */ saveFormHandler: function() { + this.source.data["product"]["configurable-matrix-serialized"] = + JSON.stringify(this.source.data["configurable-matrix"]); + delete this.source.data["configurable-matrix"]; + this.source.data["product"]["associated_product_ids_serialized"] = + JSON.stringify(this.source.data["associated_product_ids"]); + delete this.source.data["associated_product_ids"]; if (this.checkForNewAttributes()) { this.formSaveParams = arguments; this.attributeSetHandlerModal().openModal(); diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/product/product.css b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/product/product.css index cf7a314d8636e..69b45d7fc6552 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/product/product.css +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/product/product.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/actions-list.html b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/actions-list.html index b423b66971b06..290491a938b05 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/actions-list.html +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/actions-list.html @@ -1,6 +1,6 @@ @@ -41,4 +41,4 @@ "> -
\ No newline at end of file + diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-html.html b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-html.html index 8611ea9b3d03b..bb6b3556734fe 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-html.html +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-html.html @@ -1,6 +1,6 @@ @@ -10,4 +10,4 @@ css: {_disabled: disabled} "> - \ No newline at end of file + diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-status.html b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-status.html index c66c058668cff..4006a8937d2df 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-status.html +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/cell-status.html @@ -1,6 +1,6 @@ @@ -10,4 +10,4 @@ css: {_disabled: disabled} "> - \ No newline at end of file + diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/file-uploader.html b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/file-uploader.html index 8fd1604fafb10..8bdb919d138a9 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/file-uploader.html +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/components/file-uploader.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/variations/steps/summary-grid.html b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/variations/steps/summary-grid.html index 3c79b6555c6f2..4ef980d98bed8 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/variations/steps/summary-grid.html +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/template/variations/steps/summary-grid.html @@ -1,6 +1,6 @@ @@ -13,6 +13,10 @@
+ +
+ escapeHtml(__('Is Default')) ?> getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> + class="_required" + > + escapeHtml(__($_store->getName())) ?>
- + + +
+ getReadOnly() && !$block->canManageOptionDefaultOnly()):?> -
getReadOnly() && !$block->canManageOptionDefaultOnly()): ?> -
+
- getReadOnly() || $block->canManageOptionDefaultOnly()): ?> disabled="disabled"/> + getReadOnly() || $block->canManageOptionDefaultOnly()): ?> + disabled="disabled" + />
- getReadOnly()):?>disabled="disabled"/> + getReadOnly()):?>disabled="disabled"/> getReadOnly() || $block->canManageOptionDefaultOnly()):?> disabled="disabled"/> + getReadOnly() || $block->canManageOptionDefaultOnly()):?> + disabled="disabled" + /> + getReadOnly() && !$block->canManageOptionDefaultOnly()):?> -
@@ -23,7 +27,7 @@ - + ', $element->getHtmlId()); + $html .= ''; } - return $this->toHtml(); + + return $html; } } diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Payment.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Payment.php index d49403f94ebe1..3203dc55ce835 100644 --- a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Payment.php +++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Payment.php @@ -1,6 +1,6 @@
' . $element->getLegend(); + $html = '
'; $groupConfig = $element->getGroup(); - $html .= ''; - - if ($element->getComment()) { - $html .= '' . $element->getComment() . ''; - } - $html .= '
'; - $disabledAttributeString = $this->_isPaymentEnabled($element) ? '' : ' disabled="disabled"'; $disabledClassString = $this->_isPaymentEnabled($element) ? '' : ' disabled'; $htmlId = $element->getHtmlId(); @@ -121,6 +114,13 @@ protected function _getHeaderTitleHtml($element) ) . ''; } + $html .= '
'; + $html .= '
' . $element->getLegend() . ''; + + if ($element->getComment()) { + $html .= '' . $element->getComment() . ''; + } + $html .= '
'; $html .= '
'; return $html; @@ -149,4 +149,33 @@ protected function _isCollapseState($element) { return false; } + + /** + * @param \Magento\Framework\Data\Form\Element\AbstractElement $element + * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + protected function _getExtraJs($element) + { + $script = "require(['jquery', 'prototype'], function(jQuery){ + window.paypalToggleSolution = function (id, url) { + var doScroll = false; + Fieldset.toggleCollapse(id, url); + if ($(this).hasClassName(\"open\")) { + $$(\".with-button button.button\").each(function(anotherButton) { + if (anotherButton != this && $(anotherButton).hasClassName(\"open\")) { + $(anotherButton).click(); + doScroll = true; + } + }.bind(this)); + } + if (doScroll) { + var pos = Element.cumulativeOffset($(this)); + window.scrollTo(pos[0], pos[1] - 45); + } + } + });"; + + return $this->_jsHelper->getScript($script); + } } diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Payflowlink/Advanced.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Payflowlink/Advanced.php index cf8172ad0e40c..d906beaf13ab4 100644 --- a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Payflowlink/Advanced.php +++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Payflowlink/Advanced.php @@ -1,6 +1,6 @@ _cctypeFactory->create()->setAllowedTypes( - ['VI', 'MC', 'SM', 'SO', 'OT', 'AE'] + ['VI', 'MC', 'SM', 'SO', 'AE'] )->toOptionArray(); } @@ -1310,7 +1310,7 @@ public function getWppPeCcTypesAsOptionArray() */ public function getPayflowproCcTypesAsOptionArray() { - return $this->_cctypeFactory->create()->setAllowedTypes(['AE', 'VI', 'MC', 'JCB', 'DI'])->toOptionArray(); + return $this->_cctypeFactory->create()->setAllowedTypes(['AE', 'VI', 'MC', 'JCB', 'DI', 'DN'])->toOptionArray(); } /** diff --git a/app/code/Magento/Paypal/Model/Config/Factory.php b/app/code/Magento/Paypal/Model/Config/Factory.php index e30b3d58f2a9c..47cdccc94cc9f 100644 --- a/app/code/Magento/Paypal/Model/Config/Factory.php +++ b/app/code/Magento/Paypal/Model/Config/Factory.php @@ -1,6 +1,6 @@ $childData) { + if (in_array($childSection, self::$specialGroups)) { + if (isset($changedStructure[$childSection]['children'])) { + $children = $changedStructure[$childSection]['children']; + if (isset($childData['children'])) { + $children += $childData['children']; + } + $childData['children'] = $children; + unset($children); + } + $changedStructure[$childSection] = $childData; + } else { + $moveInstructions = $this->getMoveInstructions($childSection, $childData); + if (!empty($moveInstructions)) { + foreach ($moveInstructions as $moveInstruction) { + unset($childData['children'][$moveInstruction['section']]); + unset($moveInstruction['data']['displayIn']); + $changedStructure + [$moveInstruction['parent']] + ['children'] + [$moveInstruction['section']] = $moveInstruction['data']; + } + } + if (!isset($moveInstructions[$childSection])) { + $changedStructure['other_payment_methods']['children'][$childSection] = $childData; + } + } + } + + return $changedStructure; + } + + /** + * Recursively collect groups that should be moved to special section + * + * @param string $section + * @param array $data + * @return array + */ + private function getMoveInstructions($section, $data) + { + $moved = []; + + if (array_key_exists('children', $data)) { + foreach ($data['children'] as $childSection => $childData) { + $movedChildren = $this->getMoveInstructions($childSection, $childData); + if (isset($movedChildren[$childSection])) { + unset($data['children'][$childSection]); + } + $moved = array_merge($moved, $movedChildren); + } + } + + if (isset($data['displayIn']) && in_array($data['displayIn'], self::$specialGroups)) { + $moved = array_merge( + [ + $section => [ + 'parent' => $data['displayIn'], + 'section' => $section, + 'data' => $data + ] + ], + $moved + ); + } + + return $moved; + } +} diff --git a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php index 2767e438d50c0..e06e7ed8d1b50 100644 --- a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php +++ b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php @@ -1,10 +1,18 @@ _scopeDefiner = $scopeDefiner; $this->_helper = $helper; + $this->paymentSectionModifier = $paymentSectionModifier + ?: ObjectManager::getInstance()->get(PaymentSectionModifier::class); } /** @@ -69,14 +86,14 @@ public static function getPaypalConfigCountries($addOther = false) /** * Substitute payment section with PayPal configs * - * @param \Magento\Config\Model\Config\Structure $subject + * @param Structure $subject * @param \Closure $proceed * @param array $pathParts - * @return \Magento\Config\Model\Config\Structure\ElementInterface + * @return ElementInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function aroundGetElementByPathParts( - \Magento\Config\Model\Config\Structure $subject, + Structure $subject, \Closure $proceed, array $pathParts ) { @@ -89,10 +106,11 @@ public function aroundGetElementByPathParts( $pathParts[0] = 'payment_other'; } } - /** @var \Magento\Config\Model\Config\Structure\ElementInterface $result */ + /** @var ElementInterface $result */ $result = $proceed($pathParts); if ($isSectionChanged && isset($result)) { - if ($result instanceof \Magento\Config\Model\Config\Structure\Element\Section) { + if ($result instanceof Section) { + $this->restructurePayments($result); $result->setData(array_merge( $result->getData(), ['showInDefault' => true, 'showInWebsite' => true, 'showInStore' => true] @@ -101,4 +119,19 @@ public function aroundGetElementByPathParts( } return $result; } + + /** + * Changes payment config structure. + * + * @param Section $result + * @return void + */ + private function restructurePayments(Section $result) + { + $sectionData = $result->getData(); + $sectionInitialStructure = isset($sectionData['children']) ? $sectionData['children'] : []; + $sectionChangedStructure = $this->paymentSectionModifier->modify($sectionInitialStructure); + $sectionData['children'] = $sectionChangedStructure; + $result->setData($sectionData, $this->_scopeDefiner->getScope()); + } } diff --git a/app/code/Magento/Paypal/Model/Direct.php b/app/code/Magento/Paypal/Model/Direct.php index c31c708a669d1..60bb99a955d0d 100644 --- a/app/code/Magento/Paypal/Model/Direct.php +++ b/app/code/Magento/Paypal/Model/Direct.php @@ -1,6 +1,6 @@ responseValidator; } - /** * Do not validate payment form using server methods * @@ -167,6 +166,7 @@ public function authorize(InfoInterface $payment, $amount) $request->setData('trxtype', self::TRXTYPE_AUTH_ONLY); $request->setData('origid', $token); $request->setData('amt', $this->formatPrice($amount)); + $request->setData('currency', $order->getBaseCurrencyCode()); $response = $this->postRequest($request, $this->getConfig()); $this->processErrors($response); @@ -184,6 +184,7 @@ public function authorize(InfoInterface $payment, $amount) $this->createPaymentToken($payment, $token); $payment->unsAdditionalInformation(self::CC_DETAILS); + $payment->unsAdditionalInformation(self::PNREF); return $this; } diff --git a/app/code/Magento/Paypal/Model/Payflow/Ui/Adminhtml/TokenUiComponentProvider.php b/app/code/Magento/Paypal/Model/Payflow/Ui/Adminhtml/TokenUiComponentProvider.php index 7352b5b140d93..916b04fe64d4a 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Ui/Adminhtml/TokenUiComponentProvider.php +++ b/app/code/Magento/Paypal/Model/Payflow/Ui/Adminhtml/TokenUiComponentProvider.php @@ -1,6 +1,6 @@ element = $this->getMockBuilder(AbstractElement::class) + ->setMethods(['getComment', 'getHtmlId']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->block = $om->getObject(Hint::class); + } + + /** + * @covers \Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint::render + */ + public function testRender() + { + $expected = ''; + + $this->element->expects(static::exactly(2)) + ->method('getComment') + ->willReturn('http://test.com'); + + $this->element->expects(static::once()) + ->method('getHtmlId') + ->willReturn('payment'); + + static::assertSame($expected, $this->block->render($this->element)); + } + + /** + * @covers \Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint::render + */ + public function testRenderEmptyComment() + { + $this->element->expects(static::once()) + ->method('getComment') + ->willReturn(''); + + $this->element->expects(static::never()) + ->method('getHtmlId'); + + static::assertSame('', $this->block->render($this->element)); + } +} diff --git a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/PaymentTest.php b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/PaymentTest.php index 036e570e9d04e..e74d09f81d849 100644 --- a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/PaymentTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/System/Config/Fieldset/PaymentTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/FileResolverTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/FileResolverTest.php index c405ab9fdec25..898b8c0759713 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/FileResolverTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/FileResolverTest.php @@ -1,6 +1,6 @@ modify($structure); + $presentSpecialGroups = array_intersect( + self::$specialGroups, + array_keys($modifiedStructure) + ); + + $this->assertEquals( + self::$specialGroups, + $presentSpecialGroups, + sprintf('All special groups must be present in %s case', $case) + ); + } + + /** + * @param string $case + * @param array $structure + * @dataProvider caseProvider + */ + public function testOnlySpecialGroupsPresent($case, $structure) + { + $modifier = new PaymentSectionModifier(); + $modifiedStructure = $modifier->modify($structure); + $presentNotSpecialGroups = array_diff( + array_keys($modifiedStructure), + self::$specialGroups + ); + + $this->assertEquals( + [], + $presentNotSpecialGroups, + sprintf('Only special groups should be present at top level in "%s" case', $case) + ); + } + + /** + * @param string $case + * @param array $structure + * @dataProvider caseProvider + */ + public function testGroupsNotRemovedAfterModification($case, $structure) + { + $modifier = new PaymentSectionModifier(); + $modifiedStructure = $modifier->modify($structure); + + $removedGroups = array_diff( + $this->fetchAllAvailableGroups($structure), + $this->fetchAllAvailableGroups($modifiedStructure) + ); + + $this->assertEquals( + [], + $removedGroups, + sprintf('Groups should not be removed after modification in "%s" case', $case) + ); + } + + public function testMovedToTargetSpecialGroup() + { + $structure = [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + 'displayIn' => 'recommended_solutions', + ], + 'some_group' => [ + 'id' => 'some_group', + 'children' => [ + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'recommended_solutions' + ], + 'some_payment_method3' => [ + 'id' => 'some_payment_method3', + 'displayIn' => 'other_payment_methods' + ], + 'some_payment_method4' => [ + 'id' => 'some_payment_method4', + 'displayIn' => 'recommended_solutions' + ], + 'some_payment_method5' => [ + 'id' => 'some_payment_method5', + ], + ] + ], + ]; + + $modifier = new PaymentSectionModifier(); + $modifiedStructure = $modifier->modify($structure); + + $this->assertEquals( + [ + 'account' => [], + 'recommended_solutions' => [ + 'children' => [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + ], + 'some_payment_method4' => [ + 'id' => 'some_payment_method4', + ], + ], + ], + 'other_paypal_payment_solutions' => [], + 'other_payment_methods' => [ + 'children' => [ + 'some_payment_method3' => [ + 'id' => 'some_payment_method3', + ], + 'some_group' => [ + 'id' => 'some_group', + 'children' => [ + 'some_payment_method5' => [ + 'id' => 'some_payment_method5', + ], + ], + ], + ], + ], + ], + $modifiedStructure, + 'Some group is not moved correctly' + ); + } + + private function fetchAllAvailableGroups($structure) + { + $availableGroups = []; + foreach ($structure as $group => $data) { + $availableGroups[] = $group; + if (isset($data['children'])) { + $availableGroups = array_merge( + $availableGroups, + $this->fetchAllAvailableGroups($data['children']) + ); + } + } + $availableGroups = array_values(array_unique($availableGroups)); + sort($availableGroups); + return $availableGroups; + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function caseProvider() + { + return [ + [ + 'empty structure', + [] + ], + [ + 'structure with special groups at the begin of the list', + [ + 'account' => [ + 'id' => 'account', + 'children' => [ + + ] + ], + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + 'children' => [ + + ] + ], + 'other_paypal_payment_solutions' => [ + 'id' => 'other_paypal_payment_solutions', + 'children' => [ + + ] + ], + 'other_payment_methods' => [ + 'id' => 'other_payment_methods', + 'children' => [ + + ] + ], + 'some_payment_method' => [ + 'id' => 'some_payment_method', + 'children' => [ + + ] + ], + ] + ], + [ + 'structure with special groups at the end of the list', + [ + 'some_payment_method' => [ + 'id' => 'some_payment_method', + 'children' => [ + + ] + ], + 'account' => [ + 'id' => 'account', + 'children' => [ + + ] + ], + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + 'children' => [ + + ] + ], + 'other_paypal_payment_solutions' => [ + 'id' => 'other_paypal_payment_solutions', + 'children' => [ + + ] + ], + 'other_payment_methods' => [ + 'id' => 'other_payment_methods', + 'children' => [ + + ] + ], + ] + ], + [ + 'structure with special groups in the middle of the list', + [ + 'some_payment_methodq' => [ + 'id' => 'some_payment_methodq', + 'children' => [ + + ] + ], + 'account' => [ + 'id' => 'account', + 'children' => [ + + ] + ], + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + 'children' => [ + + ] + ], + 'other_paypal_payment_solutions' => [ + 'id' => 'other_paypal_payment_solutions', + 'children' => [ + + ] + ], + 'other_payment_methods' => [ + 'id' => 'other_payment_methods', + 'children' => [ + + ] + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'children' => [ + + ] + ], + ] + ], + [ + 'structure with all assigned groups', + [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + 'displayIn' => 'other_paypal_payment_solutions', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'recommended_solutions', + ], + ] + ], + [ + 'structure with not assigned groups', + [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + 'displayIn' => 'other_paypal_payment_solutions', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + ], + ] + ], + [ + 'special groups has predefined children', + [ + 'recommended_solutions' => [ + 'id' => 'recommended_solutions', + 'children' => [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + ], + ] + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'recommended_solutions', + ], + ] + ], + [ + 'structure with displayIn that do not reference to special groups', + [ + 'some_payment_method1' => [ + 'id' => 'some_payment_method1', + ], + 'some_payment_method2' => [ + 'id' => 'some_payment_method2', + 'displayIn' => 'some_payment_method1', + ], + ] + ], + ]; + } +} diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php index 0c4e4218d293d..a954ad38474da 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php @@ -1,11 +1,12 @@ _scopeDefiner = $this->getMock('Magento\Config\Model\Config\ScopeDefiner', [], [], '', false); $this->_helper = $this->getMock('Magento\Paypal\Helper\Backend', [], [], '', false); + $this->paymentSectionModifier = $this->getMockBuilder(PaymentSectionModifier::class)->getMock(); + $objectManagerHelper = new ObjectManagerHelper($this); $this->_model = $objectManagerHelper->getObject( 'Magento\Paypal\Model\Config\StructurePlugin', - ['scopeDefiner' => $this->_scopeDefiner, 'helper' => $this->_helper] + [ + 'scopeDefiner' => $this->_scopeDefiner, + 'helper' => $this->_helper, + 'paymentSectionModifier' => $this->paymentSectionModifier, + ] ); } @@ -136,15 +148,32 @@ public function testAroundGetSectionByPathParts($pathParts, $countryCode, $expec $getElementByPathParts = function ($pathParts) use ($self, $expectedPathParts, $result) { $self->assertEquals($expectedPathParts, $pathParts); $scope = 'any scope'; - $self->_scopeDefiner->expects($self->once()) + $sectionMap = [ + 'account' => [], + 'recommended_solutions' => [], + 'other_paypal_payment_solutions' => [], + 'other_payment_methods' => [] + ]; + $self->_scopeDefiner->expects($self->any()) ->method('getScope') ->will($self->returnValue($scope)); - $result->expects($self->once()) + $this->paymentSectionModifier->method('modify')->willReturn($sectionMap); + $result->expects($self->at(0)) + ->method('getData') + ->will($self->returnValue(['children' => []])); + $result->expects($self->at(2)) ->method('getData') - ->will($self->returnValue([])); - $result->expects($self->once()) + ->will($self->returnValue(['children' => $sectionMap])); + $result->expects($self->at(1)) + ->method('setData') + ->with(['children' => $sectionMap], $scope) + ->will($self->returnSelf()); + $result->expects($self->at(3)) ->method('setData') - ->with(['showInDefault' => true, 'showInWebsite' => true, 'showInStore' => true], $scope) + ->with(['children' => $sectionMap, + 'showInDefault' => true, + 'showInWebsite' => true, + 'showInStore' => true], $scope) ->will($self->returnSelf()); return $result; }; diff --git a/app/code/Magento/Paypal/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Paypal/Test/Unit/Model/ConfigTest.php index 1ac7d84b60d0e..3ba45542f7ab0 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/ConfigTest.php @@ -1,6 +1,6 @@ -2CeilingAmountTotal Purchase Price CeilingRThe purchase amount of 7501 is greater than the ceiling value set of 7500CeilingValue75.006HighOrderNumberTotal ItemCeilingR16 items were ordered, which is overthe maximum allowed quantity of 15Value157BillShipMismatchShipping/BillingMismatchRThebilling and shipping addresses did not match13HighRiskBinCheckBIN Risk List MatchRThe card number is in a high risk bin list37HighRiskZIPCheckZip Risk List MatchRHigh risk shipping zip16BillUSPostalAddressCheckUSPS Address Validation FailureRThe billing address is not a valid USAddressAddressToVerifybill \ No newline at end of file +2CeilingAmountTotal Purchase Price CeilingRThe purchase amount of 7501 is greater than the ceiling value set of 7500CeilingValue75.006HighOrderNumberTotal ItemCeilingR16 items were ordered, which is overthe maximum allowed quantity of 15Value157BillShipMismatchShipping/BillingMismatchRThebilling and shipping addresses did not match13HighRiskBinCheckBIN Risk List MatchRThe card number is in a high risk bin list37HighRiskZIPCheckZip Risk List MatchRHigh risk shipping zip16BillUSPostalAddressCheckUSPS Address Validation FailureRThe billing address is not a valid USAddressAddressToVerifybill diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Handler/_files/xxe_fps_prexmldata.xml b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Handler/_files/xxe_fps_prexmldata.xml index 98b5ef036e035..851f49fa8862b 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Handler/_files/xxe_fps_prexmldata.xml +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/Handler/_files/xxe_fps_prexmldata.xml @@ -1,7 +1,7 @@ @@ -68,4 +68,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/TransactionTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/TransactionTest.php index b4601c46a898f..352eeb38a6096 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/TransactionTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Response/TransactionTest.php @@ -1,6 +1,6 @@ disableOriginalConstructor() ->getMock(); - $this->paymentTokenFactory = $this->getMockBuilder('\Magento\Vault\Api\Data\PaymentTokenInterfaceFactory') + $this->paymentTokenFactory = $this->getMockBuilder(CreditCardTokenFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); @@ -122,7 +122,7 @@ protected function initializationAuthorizeMock() $this->orderMock = $this->getMockBuilder('Magento\Sales\Model\Order') ->setMethods([ 'getCustomerId', 'getBillingAddress', 'getShippingAddress', 'getCustomerEmail', - 'getId', 'getIncrementId' + 'getId', 'getIncrementId', 'getBaseCurrencyCode' ]) ->disableOriginalConstructor() ->getMock(); @@ -164,6 +164,9 @@ protected function buildRequestData() $this->paymentMock->expects($this->once()) ->method('getOrder') ->willReturn($this->orderMock); + $this->orderMock->expects($this->once()) + ->method('getBaseCurrencyCode') + ->willReturn('USD'); $this->orderMock->expects($this->once()) ->method('getBillingAddress') ->willReturn($this->addressBillingMock); @@ -425,6 +428,13 @@ public function testAuthorize() ->method('setVaultPaymentToken') ->with($paymentTokenMock); + $this->paymentMock->expects($this->at(8)) + ->method('unsAdditionalInformation') + ->with(Transparent::CC_DETAILS); + $this->paymentMock->expects($this->at(9)) + ->method('unsAdditionalInformation') + ->with(Transparent::PNREF); + $this->assertSame($this->object, $this->object->authorize($this->paymentMock, 33)); } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/PayflowConfigTest.php b/app/code/Magento/Paypal/Test/Unit/Model/PayflowConfigTest.php index 68d0b75997071..094e819a9209f 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/PayflowConfigTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/PayflowConfigTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/di.xml b/app/code/Magento/Paypal/etc/adminhtml/di.xml index 0ae9d9569969d..4e4c1c2f6e4d0 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/di.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ @@ -42,6 +42,7 @@ + Magento\Vault\Model\CreditCardTokenFactory Magento\Paypal\Block\Adminhtml\Payflowpro\CcForm diff --git a/app/code/Magento/Paypal/etc/adminhtml/events.xml b/app/code/Magento/Paypal/etc/adminhtml/events.xml index 818ef3f0d7011..889285f2d944c 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/events.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/menu.xml b/app/code/Magento/Paypal/etc/adminhtml/menu.xml index bff8e4c891cb9..899a71f1e8bd0 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/menu.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/routes.xml b/app/code/Magento/Paypal/etc/adminhtml/routes.xml index 136d638136e0c..b4fd844e769e8 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/routes.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_au.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_au.xml index 4ee83da9c2ab8..391e4d4e0466b 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_au.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_au.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_ca.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_ca.xml index fb2b7456fb7c5..0e7e5ff688dbf 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_ca.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_ca.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_de.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_de.xml index 6724aaff2413d..7e3f8b8c274a9 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_de.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_de.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_es.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_es.xml index 98f69db7f949d..e19a9ec557479 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_es.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_es.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_fr.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_fr.xml index 8b4a71c177e91..0c0a8eb2da4d4 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_fr.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_fr.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_gb.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_gb.xml index f6e1d4376ad97..dc6ba04bf909a 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_gb.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_gb.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_hk.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_hk.xml index 6e27406c6734a..28fd038971a04 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_hk.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_hk.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_it.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_it.xml index a65983c5835de..55d788ee7b5b7 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_it.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_it.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_jp.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_jp.xml index cb6caa9000418..d9cd73cb6a302 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_jp.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_jp.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_nz.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_nz.xml index 379fd221f2821..f65a16ad6da86 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_nz.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_nz.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_other.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_other.xml index 49320b22158d8..40fde95c44a62 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_other.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_other.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml index dfbb68283daa9..93434be69a0d0 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/adminhtml/system.xml b/app/code/Magento/Paypal/etc/adminhtml/system.xml index 4fdee80a457bc..8418228bb909c 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system.xml @@ -1,17 +1,13 @@
- - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint - https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded @@ -24,6 +20,21 @@ paypal/general/merchant_country + + + paypal-top-section paypal-recommended-header + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded + + + + paypal-top-section paypal-other-header + \Magento\Config\Block\System\Config\Form\Fieldset + + + + paypal-top-section payments-other-header + \Magento\Config\Block\System\Config\Form\Fieldset +
@@ -38,21 +49,33 @@
-
- - - 1 - complex - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group +
+ + + + complex paypal-express-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment + Add another payment method to your existing solution or as a stand-alone option. + https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content + 0 + payment/paypal_express/active + payment/payflow_express/active + recommended_solutions + + + + + complex paypal-other-section paypal-all-in-one-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded Choose a secure bundled payment solution for your business. - https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&subTab=newlineup + other_paypal_payment_solutions - - + + payment/paypal_payment_pro/active - https://www.paypal.com/us/webapps/mpp/paypal-payments-pro?partner_id=NB9WWHYEMVUMS + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html + 0 @@ -70,6 +93,9 @@ Accept credit card and PayPal payments securely. payment/wps_express/active + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html + @@ -88,42 +114,40 @@ - - - complex - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group - Process payments using your own internet merchant account. - https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content + + + complex paypal-other-section paypal-gateways-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded + other_paypal_payment_solutions - - - 1 - complex - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group - Add another payment method to your existing solution or as a stand-alone option. - https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content - - 0 - payment/paypal_express/active - payment/payflow_express/active - -
- - - 1 - complex - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group + + + + complex paypal-express-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment + Add another payment method to your existing solution or as a stand-alone option. + https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content + recommended_solutions + + + + + + + + + complex paypal-other-section paypal-all-in-one-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded Choose a secure bundled payment solution for your business. https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&subTab=newlineup + other_paypal_payment_solutions pp-general-uk - https://www.paypal-business.co.uk/process-online-payments-with-paypal/index.htm http://www.youtube.com/watch?v=LBe-TW87eGI&list=PLF18B1094ABCD7CE8&index=1&feature=plpp_video Accept payments with a completely customizable checkout page. @@ -137,6 +161,9 @@ Accept credit card and PayPal payments securely. payment/wps_express/active + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html + @@ -155,31 +182,16 @@ - - - 1 - complex - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group - Add another payment method to your existing solution or as a stand-alone option. - https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content - - - - - - -
- - - 1 - complex - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group - Add another payment method to your existing solution or as a stand-alone option. - https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&subTab=newlineup - + + + + complex paypal-express-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment + Add another payment method to your existing solution or as a stand-alone option. + https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&subTab=newlineup + recommended_solutions @@ -194,17 +206,35 @@
- - - 1 - complex - Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group + + + complex paypal-express-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment Add another payment method to your existing solution or as a stand-alone option. https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&subTab=newlineup - + recommended_solutions + + + + + + + + complex paypal-other-section paypal-all-in-one-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded + Choose a secure bundled payment solution for your business. + https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&subTab=newlineup + other_paypal_payment_solutions + + complex + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment Accept credit card and PayPal payments securely. payment/wps_express/active + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-standard.html + @@ -222,21 +252,34 @@ - - - - - - + + + + complex paypal-other-section paypal-gateways-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded + Process payments using your own internet merchant account. + https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content + other_paypal_payment_solutions
- + + payment/paypal_express/active + payment/payflow_express/active + + - + + + complex paypal-other-section paypal-gateways-section + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded + + payment/paypal_payment_pro/active + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html + @@ -254,76 +297,76 @@ - - + + - - payment/paypal_express/active - payment/payflow_express/active -
- - - + + + + + + -
- + + -
- + + -
- + + -
- + + -
- + + -
- - - - + + + + + +
diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml index 8972bcbc5def5..3234925202357 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml @@ -1,7 +1,7 @@ @@ -9,10 +9,13 @@ Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment - pp-method-express + paypal-other-section Add PayPal as an additional payment method to your checkout page. payment/paypal_express/active - https://www.paypal.com/webapps/mpp/referral/paypal-express-checkout?partner_id=NB9WWHYEMVUMS + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-express-checkout.html + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded @@ -20,7 +23,8 @@ Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded - + + not-required Start accepting payments via PayPal!]]> diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml index fdb3d0e08df73..1e19a81fb953f 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_advanced.xml @@ -1,18 +1,21 @@ - - pp-method-general + + paypal-other-section Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment - https://www.paypal.com/webapps/mpp/referral/paypal-payments-advanced?partner_id=NB9WWHYEMVUMS - Accept payments with a PCI-compliant checkout that keeps customers on your site. + Includes Express Checkout)]]> payment/payflow_advanced/active + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-advanced.html + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml index f6f2829b11424..500465c74a7dc 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/payflow_link.xml @@ -1,18 +1,21 @@ - + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment - pp-method-payflow - Connect your merchant account with a PCI-compliant gateway that lets customers pay without leaving your site. + paypal-other-section + Includes Express Checkout)]]> payment/payflow_link/active - https://www.paypal.com/webapps/mpp/referral/paypal-payflow-link?partner_id=NB9WWHYEMVUMS + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payflow-link.html + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml b/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml index 2f92c17c142aa..44b288f86f308 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution.xml @@ -1,18 +1,22 @@ - pp-method-general + paypal-other-section Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment payment/hosted_pro/active - Accept payments with a PCI compliant checkout that keeps customers on your site. + Includes Express Checkout)]]> 1 + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payments-pro.html + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution_with_express_checkout.xml b/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution_with_express_checkout.xml index 570d09201ff1e..f2536714af294 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution_with_express_checkout.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/payments_pro_hosted_solution_with_express_checkout.xml @@ -1,15 +1,13 @@ - - - pp-general-uk - https://cms.paypal.com/cms_content/GB/en_GB/files/developer/HostedSolution.pdf + + 0 diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml b/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml index 2150d5dcb392b..d5652e602d1db 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro.xml @@ -1,7 +1,7 @@ @@ -9,11 +9,14 @@ Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment - pp-method-payflow - Connect your merchant account with a fully customizable gateway that lets customers pay without leaving your site. + paypal-other-section + Includes Express Checkout)]]> payment/payflowpro/active - https://www.paypal.com/webapps/mpp/payflow-payment-gateway?partner_id=NB9WWHYEMVUMS 1 + + http://docs.magento.com/m2/ce/user_guide/payment/paypal-payflow-pro.html + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Hint + Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Expanded @@ -81,7 +84,7 @@ - + Magento\Config\Model\Config\Source\Yesno payment/payflowpro_cc_vault/active 1 diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro_with_express_checkout.xml b/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro_with_express_checkout.xml index d347ecd9c532a..98df65a24071c 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro_with_express_checkout.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/paypal_payflowpro_with_express_checkout.xml @@ -1,13 +1,13 @@ - + 0 diff --git a/app/code/Magento/Paypal/etc/config.xml b/app/code/Magento/Paypal/etc/config.xml index 2fe6ecefc17bd..f72b9324beeb5 100644 --- a/app/code/Magento/Paypal/etc/config.xml +++ b/app/code/Magento/Paypal/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/crontab.xml b/app/code/Magento/Paypal/etc/crontab.xml index ce87612dcac81..0c2877cfc08e9 100644 --- a/app/code/Magento/Paypal/etc/crontab.xml +++ b/app/code/Magento/Paypal/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/di.xml b/app/code/Magento/Paypal/etc/di.xml index 8b287d08e77a4..95cc3f1c876c2 100644 --- a/app/code/Magento/Paypal/etc/di.xml +++ b/app/code/Magento/Paypal/etc/di.xml @@ -1,7 +1,7 @@ @@ -176,4 +176,37 @@ + + + Magento\Vault\Model\CreditCardTokenFactory + + + + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + diff --git a/app/code/Magento/Paypal/etc/events.xml b/app/code/Magento/Paypal/etc/events.xml index daf29e6ceca11..630df6ba2f2d8 100644 --- a/app/code/Magento/Paypal/etc/events.xml +++ b/app/code/Magento/Paypal/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/frontend/di.xml b/app/code/Magento/Paypal/etc/frontend/di.xml index 8b98901f53150..7ababeb54b551 100644 --- a/app/code/Magento/Paypal/etc/frontend/di.xml +++ b/app/code/Magento/Paypal/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/frontend/events.xml b/app/code/Magento/Paypal/etc/frontend/events.xml index 6175340caa1e3..409609fe98810 100644 --- a/app/code/Magento/Paypal/etc/frontend/events.xml +++ b/app/code/Magento/Paypal/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/frontend/page_types.xml b/app/code/Magento/Paypal/etc/frontend/page_types.xml index 1c8b200632ab5..2a38db3e2ca87 100644 --- a/app/code/Magento/Paypal/etc/frontend/page_types.xml +++ b/app/code/Magento/Paypal/etc/frontend/page_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/frontend/routes.xml b/app/code/Magento/Paypal/etc/frontend/routes.xml index e1fc0b5904294..f08bfbb4acc92 100644 --- a/app/code/Magento/Paypal/etc/frontend/routes.xml +++ b/app/code/Magento/Paypal/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Paypal/etc/frontend/sections.xml b/app/code/Magento/Paypal/etc/frontend/sections.xml index bc8e4720a46eb..94f120ef70786 100644 --- a/app/code/Magento/Paypal/etc/frontend/sections.xml +++ b/app/code/Magento/Paypal/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/module.xml b/app/code/Magento/Paypal/etc/module.xml index 522850d28bfde..62a8c1abf6b5a 100644 --- a/app/code/Magento/Paypal/etc/module.xml +++ b/app/code/Magento/Paypal/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/payment.xml b/app/code/Magento/Paypal/etc/payment.xml index e7d98abea49c8..22c616ac4baf1 100644 --- a/app/code/Magento/Paypal/etc/payment.xml +++ b/app/code/Magento/Paypal/etc/payment.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/etc/rules.xsd b/app/code/Magento/Paypal/etc/rules.xsd index 6852b07547b80..27dca202b0c74 100644 --- a/app/code/Magento/Paypal/etc/rules.xsd +++ b/app/code/Magento/Paypal/etc/rules.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/i18n/en_US.csv b/app/code/Magento/Paypal/i18n/en_US.csv index ad97afb85e65e..5c3bf52d825b9 100644 --- a/app/code/Magento/Paypal/i18n/en_US.csv +++ b/app/code/Magento/Paypal/i18n/en_US.csv @@ -677,4 +677,6 @@ User,User The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15% or more. See Details. " -"payflowpro","Payflow Pro" \ No newline at end of file +"payflowpro","Payflow Pro" +"Payments Pro","Payments Pro" +"Website Payments Pro","Website Payments Pro" \ No newline at end of file diff --git a/app/code/Magento/Paypal/registration.php b/app/code/Magento/Paypal/registration.php index 884b58364ffb8..88ee368822f4b 100644 --- a/app/code/Magento/Paypal/registration.php +++ b/app/code/Magento/Paypal/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_system_config_edit.xml b/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_system_config_edit.xml index 96901cae0348a..23df770757e60 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_system_config_edit.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/adminhtml_system_config_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/customer_index_edit.xml b/app/code/Magento/Paypal/view/adminhtml/layout/customer_index_edit.xml index d6a52c99569d2..0a21e0edd8286 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/customer_index_edit.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/customer_index_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_customergrid.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_customergrid.xml index d4b9324338194..451748ff1673e 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_customergrid.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_customergrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_grid.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_grid.xml index ec035dce0ebf8..6a672ab4f6ba5 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_grid.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_index.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_index.xml index 133c311462e34..5ad15e7b24a85 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_index.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml index e32876475f824..16f6eaae71c88 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml index 39930b2e764a6..f6a90e58f5acc 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_grid.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_grid.xml index 9281651974e2b..6c0487a6f8beb 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_grid.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_index.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_index.xml index a4eb25a660593..702673054f338 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_index.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_paypal_reports_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_index.xml b/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_index.xml index c858a29e9a1de..38099cdb03527 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_index.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_index.xml @@ -1,7 +1,7 @@ @@ -20,4 +20,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml b/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml index ffd0d656ba550..a76eff625c5e7 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml @@ -1,7 +1,7 @@ @@ -20,4 +20,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/transparent_payment_response.xml b/app/code/Magento/Paypal/view/adminhtml/layout/transparent_payment_response.xml index 57764653946f7..9ef0a1eac456e 100644 --- a/app/code/Magento/Paypal/view/adminhtml/layout/transparent_payment_response.xml +++ b/app/code/Magento/Paypal/view/adminhtml/layout/transparent_payment_response.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml index 47d93bb377e31..8038a41aa8e2b 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/view/tab/info.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/view/tab/info.phtml index e64b2be7fc94c..4d10dc58e13b7 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/view/tab/info.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/view/tab/info.phtml @@ -1,6 +1,6 @@ - diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml index 122d0a7a64d99..eb343abe96028 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/payflowlink/advanced.phtml @@ -1,6 +1,6 @@ .entry-edit-head > a::before {left: auto !important; right: 1.3rem !important;} +.paypal-all-in-one-section > .entry-edit-head {background: url("images/AM_mc_vs_dc_ae.jpg") no-repeat scroll 0 50% / 18rem auto; padding-left: 18rem;} +.paypal-gateways-section > .entry-edit-head {background: url("images/pp-payflow-mark.png") no-repeat scroll 0 50% / 18rem auto; padding-left: 18rem;} +.paypal-top-section > .entry-edit-head.admin__collapsible-block {border-bottom: 0;} +.paypal-top-section.active > .entry-edit-head.admin__collapsible-block {border-bottom: 1px solid #ccc;} +.paypal-top-section > .admin__collapsible-block > a {font-size: 1.4rem; font-weight: normal; text-transform: uppercase;} +.paypal-recommended-header > .admin__collapsible-block > a::before {content: "" !important;} +.paypal-other-header > .admin__collapsible-block > a::before {content: '' !important; width: 0; height: 0; border-color: transparent; border-top-color: #000; border-style: solid; border-width: .8rem .5rem 0 .5rem; margin-top:1px; transition: all .2s linear;} +.paypal-other-header > .admin__collapsible-block > a.open::before {border-color: transparent; border-bottom-color: #000; border-width: 0 .5rem .8rem .5rem;} +.paypal-other-header > .admin__collapsible-block > a {color: #007bdb !important; text-align: right;} +.payments-other-header > .admin__collapsible-block > a {display: inline-block;} +.payments-other-header > .admin__collapsible-block > a::before {content: '' !important; width: 0; height: 0; border-color: transparent; border-top-color: #000; border-style: solid; border-width: .8rem .5rem 0 .5rem; margin-top:1px; transition: all .2s linear;} +.payments-other-header > .admin__collapsible-block > a.open::before {border-color: transparent; border-bottom-color: #000; border-width: 0 .5rem .8rem .5rem;} diff --git a/app/code/Magento/Paypal/view/base/requirejs-config.js b/app/code/Magento/Paypal/view/base/requirejs-config.js index 0f23ee288d2d7..a235ed160ddd0 100644 --- a/app/code/Magento/Paypal/view/base/requirejs-config.js +++ b/app/code/Magento/Paypal/view/base/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,4 +9,4 @@ var config = { transparent: 'Magento_Payment/transparent' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml b/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml index 214d878534ac5..87be35546d480 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml index 3b91748bf0ce7..5d8c42a725b09 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml index 750455a004f2c..9bb63e302288c 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml index 81567a2a94167..b6bfcd9cfe0d1 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ @@ -61,4 +61,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_review.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_review.xml index 5b68af1cb43b6..67ce380dcd2c3 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_review.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_review.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_success.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_success.xml index 83aa1080d3bd7..930fff1d92f3f 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_success.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_success.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml b/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml index cfb739e2e5733..debdd786d1bd1 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/customer_account.xml b/app/code/Magento/Paypal/view/frontend/layout/customer_account.xml index 5a355a2c39967..4fcaab7c9228a 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/customer_account.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/customer_account.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/default.xml b/app/code/Magento/Paypal/view/frontend/layout/default.xml index 27b599bf2e79d..699e4ebc0dbb5 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/default.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_index.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_index.xml index 547b10f6b155f..ab9a23162d8f4 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_index.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_view.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_view.xml index e266da1aaf65b..4647e9372fd9e 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_view.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_billing_agreement_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml index d04b320378552..e4fd68de19d86 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml index 5281380a2f0a7..6cc98fade88df 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_cancelpayment.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_cancelpayment.xml index 35a74809b08bb..f0a65cc0b5d9c 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_cancelpayment.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_cancelpayment.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_form.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_form.xml index 3b47fa7302926..dac2ab927f622 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_form.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_returnurl.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_returnurl.xml index 35a74809b08bb..f0a65cc0b5d9c 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_returnurl.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflow_returnurl.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_cancelpayment.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_cancelpayment.xml index c853586806b5f..77d26dfa27d9c 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_cancelpayment.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_cancelpayment.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_form.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_form.xml index b3d22c44809b5..8bf1d33fcef7f 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_form.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_returnurl.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_returnurl.xml index c853586806b5f..77d26dfa27d9c 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_returnurl.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowadvanced_returnurl.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml index 7738aea3cab9a..4dbe84f239863 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/transparent_payment_response.xml b/app/code/Magento/Paypal/view/frontend/layout/transparent_payment_response.xml index a75c704defe58..576b350708b40 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/transparent_payment_response.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/transparent_payment_response.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/layout/vault_cards_listaction.xml b/app/code/Magento/Paypal/view/frontend/layout/vault_cards_listaction.xml index 11ff13eed9196..0a27a89f96fe5 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/vault_cards_listaction.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/vault_cards_listaction.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Paypal/view/frontend/requirejs-config.js b/app/code/Magento/Paypal/view/frontend/requirejs-config.js index 7a4a356b9d40a..11475911f74d8 100644 --- a/app/code/Magento/Paypal/view/frontend/requirejs-config.js +++ b/app/code/Magento/Paypal/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml index 95def49290b1c..bf0d4a1aba349 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml @@ -1,6 +1,6 @@ -getChildHtml(); ?> \ No newline at end of file +getChildHtml(); ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/partner/logo.phtml b/app/code/Magento/Paypal/view/frontend/templates/partner/logo.phtml index 0a4bcea937b66..afd2ee688a948 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/partner/logo.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/partner/logo.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/view/frontend/web/template/payment/iframe-methods.html b/app/code/Magento/Paypal/view/frontend/web/template/payment/iframe-methods.html index eeb69f6799761..6f0530caf912f 100644 --- a/app/code/Magento/Paypal/view/frontend/web/template/payment/iframe-methods.html +++ b/app/code/Magento/Paypal/view/frontend/web/template/payment/iframe-methods.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express-bml.html b/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express-bml.html index b49a06fb71cf5..629fd69d1f3d2 100644 --- a/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express-bml.html +++ b/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express-bml.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express.html b/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express.html index 7c51492850000..3986d01333075 100644 --- a/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express.html +++ b/app/code/Magento/Paypal/view/frontend/web/template/payment/payflow-express.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Paypal/view/frontend/web/template/payment/payflowpro-form.html b/app/code/Magento/Paypal/view/frontend/web/template/payment/payflowpro-form.html index da1da321fe621..92069469a82a2 100644 --- a/app/code/Magento/Paypal/view/frontend/web/template/payment/payflowpro-form.html +++ b/app/code/Magento/Paypal/view/frontend/web/template/payment/payflowpro-form.html @@ -1,6 +1,6 @@ @@ -51,8 +51,8 @@ -
+ getChildHtml(); ?> isSingleStoreMode() == false):?> 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 df8a21240a14d..71b27dd966b90 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 @@ -1,6 +1,6 @@ @@ -12,6 +12,7 @@ sales_order_creditmemo_grid.sales_order_creditmemo_grid_data_sourcesales_order_creditmemo_columns + Magento_Sales::sales_creditmemo diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml index e0a5471b1e45e..fab43830ef493 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml @@ -1,7 +1,7 @@ @@ -20,6 +20,7 @@ sales/order_create/start + Magento_Sales::sales_order diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml index 51671ff53d694..73a861d798736 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_invoice_grid.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ sales_order_invoice_grid.sales_order_invoice_grid_data_source sales_order_invoice_columns + Magento_Sales::sales_invoice diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml index 7eac69bf68c67..7e94feeb36acc 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_shipment_grid.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ sales_order_shipment_grid.sales_order_shipment_grid_data_source sales_order_shipment_columns + Magento_Sales::shipment diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml index cb1a60eb081f2..f39eb09eaf815 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ sales_order_view_creditmemo_grid.sales_order_view_creditmemo_grid_data_source sales_order_creditmemo_columns + Magento_Sales::sales_creditmemo diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml index a545240534258..62f661db3e612 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_invoice_grid.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ sales_order_view_invoice_grid.sales_order_view_invoice_grid_data_source sales_order_invoice_columns + Magento_Sales::sales_invoice diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml index 973986b77fbb6..eebe4485995f5 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_shipment_grid.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ sales_order_view_shipment_grid.sales_order_view_shipment_grid_data_source sales_order_shipment_columns + Magento_Sales::shipment diff --git a/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-create-index.js b/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-create-index.js index f46cd2dcf9b91..aae4d599a89e0 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-create-index.js +++ b/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-create-index.js @@ -1,8 +1,8 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ require([ "Magento_Sales/order/create/giftmessage" -]); \ No newline at end of file +]); diff --git a/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-post-action.js b/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-post-action.js index f2f2229c4280f..6dc709bb4ee2f 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-post-action.js +++ b/app/code/Magento/Sales/view/adminhtml/web/js/bootstrap/order-post-action.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/form.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/form.js index f6987cde300b3..c4f66cc06cdc6 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/create/form.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -31,4 +31,4 @@ define([ window.order = order; window.payment = payment; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/giftmessage.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/giftmessage.js index 5bdd711fd6526..c2963f811dd7c 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/create/giftmessage.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/giftmessage.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /********************* GIFT OPTIONS POPUP ***********************/ @@ -302,4 +302,4 @@ GiftMessageSet.prototype = { } }; -}); \ No newline at end of file +}); 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 e97097aecacc7..f30568215befd 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 @@ -1,6 +1,6 @@ // jscs:disable /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/edit/message.js b/app/code/Magento/Sales/view/adminhtml/web/order/edit/message.js index 41daf16b772d1..b82f7f22a2d54 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/edit/message.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/edit/message.js @@ -1,7 +1,7 @@ /** * @category Mage * @package Magento_Sales - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/giftoptions_tooltip.js b/app/code/Magento/Sales/view/adminhtml/web/order/giftoptions_tooltip.js index 111435e5e1dfc..f009b9d1fb5e4 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/giftoptions_tooltip.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/giftoptions_tooltip.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** @@ -191,4 +191,4 @@ GiftOptionsTooltip.prototype = { window.giftOptionsTooltip = new GiftOptionsTooltip(); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/view/post-wrapper.js b/app/code/Magento/Sales/view/adminhtml/web/order/view/post-wrapper.js index f688b0f8623c4..132b76adfde3b 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/view/post-wrapper.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/view/post-wrapper.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Sales/view/frontend/email/creditmemo_new.html b/app/code/Magento/Sales/view/frontend/email/creditmemo_new.html index 5f9fb3d0574de..77a96a538aa30 100644 --- a/app/code/Magento/Sales/view/frontend/email/creditmemo_new.html +++ b/app/code/Magento/Sales/view/frontend/email/creditmemo_new.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/creditmemo_new_guest.html b/app/code/Magento/Sales/view/frontend/email/creditmemo_new_guest.html index 44e09b34f1cf1..c94d58b53234c 100644 --- a/app/code/Magento/Sales/view/frontend/email/creditmemo_new_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/creditmemo_new_guest.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html b/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html index 52b6452912620..ab147750d1284 100644 --- a/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html +++ b/app/code/Magento/Sales/view/frontend/email/creditmemo_update.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html b/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html index d5ff2750efd9f..ce6ebd761ce13 100644 --- a/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/creditmemo_update_guest.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/invoice_new.html b/app/code/Magento/Sales/view/frontend/email/invoice_new.html index 4878597b55bee..7dad8fbda1f53 100644 --- a/app/code/Magento/Sales/view/frontend/email/invoice_new.html +++ b/app/code/Magento/Sales/view/frontend/email/invoice_new.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/invoice_new_guest.html b/app/code/Magento/Sales/view/frontend/email/invoice_new_guest.html index 4a4176bfc8ef6..c35249c1aff4b 100644 --- a/app/code/Magento/Sales/view/frontend/email/invoice_new_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/invoice_new_guest.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/invoice_update.html b/app/code/Magento/Sales/view/frontend/email/invoice_update.html index 32bb4eefd89e6..6f3c897b0f104 100644 --- a/app/code/Magento/Sales/view/frontend/email/invoice_update.html +++ b/app/code/Magento/Sales/view/frontend/email/invoice_update.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html b/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html index d64688476c0cc..093988329fbe3 100644 --- a/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/invoice_update_guest.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/order_new.html b/app/code/Magento/Sales/view/frontend/email/order_new.html index bb2b0bddd8267..f6766086862d3 100644 --- a/app/code/Magento/Sales/view/frontend/email/order_new.html +++ b/app/code/Magento/Sales/view/frontend/email/order_new.html @@ -1,6 +1,6 @@ @@ -12,7 +12,7 @@ "layout handle=\"sales_email_order_items\" order=$order area=\"frontend\"":"Order Items Grid", "var payment_html|raw":"Payment Details", "var formattedShippingAddress|raw":"Shipping Address", -"var order.getShippingDescription()":"Shipping Description" +"var order.getShippingDescription()":"Shipping Description", "var shipping_msg":"Shipping message" } @--> diff --git a/app/code/Magento/Sales/view/frontend/email/order_new_guest.html b/app/code/Magento/Sales/view/frontend/email/order_new_guest.html index 40d55011a035e..9768f6af37399 100644 --- a/app/code/Magento/Sales/view/frontend/email/order_new_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/order_new_guest.html @@ -1,6 +1,6 @@ @@ -14,7 +14,7 @@ "layout handle=\"sales_email_order_items\" order=$order":"Order Items Grid", "var payment_html|raw":"Payment Details", "var formattedShippingAddress|raw":"Shipping Address", -"var order.getShippingDescription()":"Shipping Description" +"var order.getShippingDescription()":"Shipping Description", "var shipping_msg":"Shipping message" } @--> {{template config_path="design/email/header_template"}} diff --git a/app/code/Magento/Sales/view/frontend/email/order_update.html b/app/code/Magento/Sales/view/frontend/email/order_update.html index d90070e51db03..dac3af4b437ab 100644 --- a/app/code/Magento/Sales/view/frontend/email/order_update.html +++ b/app/code/Magento/Sales/view/frontend/email/order_update.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/order_update_guest.html b/app/code/Magento/Sales/view/frontend/email/order_update_guest.html index 4167c93a70825..4a038a87e12b5 100644 --- a/app/code/Magento/Sales/view/frontend/email/order_update_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/order_update_guest.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/shipment_new.html b/app/code/Magento/Sales/view/frontend/email/shipment_new.html index 64bd22ce9cc22..d326e4d9a88fa 100644 --- a/app/code/Magento/Sales/view/frontend/email/shipment_new.html +++ b/app/code/Magento/Sales/view/frontend/email/shipment_new.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/shipment_new_guest.html b/app/code/Magento/Sales/view/frontend/email/shipment_new_guest.html index bda4d0628cafe..ddb6b1065a859 100644 --- a/app/code/Magento/Sales/view/frontend/email/shipment_new_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/shipment_new_guest.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/shipment_update.html b/app/code/Magento/Sales/view/frontend/email/shipment_update.html index b126b56c7af4d..8ec993e32344c 100644 --- a/app/code/Magento/Sales/view/frontend/email/shipment_update.html +++ b/app/code/Magento/Sales/view/frontend/email/shipment_update.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html b/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html index afbb4a1b622a2..912fcf2077189 100644 --- a/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html +++ b/app/code/Magento/Sales/view/frontend/email/shipment_update_guest.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Sales/view/frontend/layout/checkout_index_index.xml index 61a9ad253bc94..a0daa9e2daff3 100644 --- a/app/code/Magento/Sales/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Sales/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/customer_account.xml b/app/code/Magento/Sales/view/frontend/layout/customer_account.xml index a3933b8b22110..58ef5e28e5576 100644 --- a/app/code/Magento/Sales/view/frontend/layout/customer_account.xml +++ b/app/code/Magento/Sales/view/frontend/layout/customer_account.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/customer_account_index.xml b/app/code/Magento/Sales/view/frontend/layout/customer_account_index.xml index bf62f4c5c3a4e..ada874d0314cd 100644 --- a/app/code/Magento/Sales/view/frontend/layout/customer_account_index.xml +++ b/app/code/Magento/Sales/view/frontend/layout/customer_account_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/default.xml b/app/code/Magento/Sales/view/frontend/layout/default.xml index 348aa7e8af742..d3e767a2a26d7 100644 --- a/app/code/Magento/Sales/view/frontend/layout/default.xml +++ b/app/code/Magento/Sales/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_item_price.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_item_price.xml index d913c9dd175b0..5197ce06947ea 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_item_price.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_item_price.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_items.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_items.xml index e014663ac0958..55c7cd7ad15f0 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_items.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_items.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 481bbcf5ac2ee..1db0975f216a7 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_items.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_items.xml index bde780281db76..ea741a01a6e21 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_items.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_items.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_renderers.xml index 01903eb92a51e..975c8acaa84b0 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_items.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_items.xml index 9638593f2a2a6..75adeaaca849b 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_items.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_items.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_renderers.xml index 0c0e6e57a8ba4..66b17a5eb6350 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_items.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_items.xml index fce02ca848b05..10e4de08baaea 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_items.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_items.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_renderers.xml index 76d5bd25c7ed3..8859a6d978924 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_email_order_shipment_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_creditmemo.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_creditmemo.xml index a339a7565dbc8..22d776c1f6134 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_creditmemo.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_creditmemo.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_form.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_form.xml index 3332895226e18..edfb0a18333c2 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_form.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_invoice.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_invoice.xml index b064f55048915..5728e03a12138 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_invoice.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_invoice.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml index 8530fb4ec6f49..df4ef415cfec1 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_printcreditmemo.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_printcreditmemo.xml index fbdc78e414fb9..c481c81ded005 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_printcreditmemo.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_printcreditmemo.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_printinvoice.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_printinvoice.xml index 72b32b35e479d..4f6cac3bf2f14 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_printinvoice.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_printinvoice.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_printshipment.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_printshipment.xml index 50044820a7c9a..64c137cf0d6bc 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_printshipment.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_printshipment.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_reorder.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_reorder.xml index 7bfe897f1d102..d03d109fd6176 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_reorder.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_reorder.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_shipment.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_shipment.xml index 5b679c20ce640..1bcb0d235a77b 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_shipment.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_shipment.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_view.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_view.xml index 40a7586b479fd..0c7be2e80a2a5 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_view.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml index 8bb29507d80cd..0d86d6f9c773d 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo_renderers.xml index 6fd4a1359b135..b3cac3a808780 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_guest_info_links.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_guest_info_links.xml index 12f3adec22686..52a5410a78897 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_guest_info_links.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_guest_info_links.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_history.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_history.xml index 85b8a83a198f5..d572268ce32e5 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_history.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_history.xml @@ -1,7 +1,7 @@ @@ -11,6 +11,12 @@ + + + + diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml index a7fb903d59513..b903c41a21367 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml index 87952cb8b5a00..f4f5f4b9bbb5b 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice_renderers.xml index 6750c89c6d260..c7729cc170544 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_item_price.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_item_price.xml index f95f766587181..f27fc60b1a466 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_item_price.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_item_price.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_item_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_item_renderers.xml index a42d21a21bb5e..9fb01a4e63cd4 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_item_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml index aed3af4982495..2d1eee431735b 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_creditmemo_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_creditmemo_renderers.xml index fc2ffd95e2728..5ce4d24ee5ed1 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_creditmemo_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_invoice_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_invoice_renderers.xml index 48432c3eb27f1..6e902d6ce85d0 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_invoice_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_renderers.xml index 2d1d3fae8f9f1..4ecb2e99768e2 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_shipment_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_shipment_renderers.xml index da733092618cb..1658c8028b16b 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_print_shipment_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_print_shipment_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml index ccbf723653bc7..21cf3c8c29ab1 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml index bad93a25d6132..2a4ec65253754 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml index d8e8ca5954f45..ead04c783ebd4 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_reorder.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_reorder.xml index 6c2fca6fc6d08..1e4dcaf2bf6e3 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_reorder.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_reorder.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml index 2f6c1e77a556c..b292de7e3b012 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment_renderers.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment_renderers.xml index 3ebd143375227..27bcff9ba8add 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment_renderers.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml index 9b417f5dd94b4..4bf37ca59189e 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sales/view/frontend/requirejs-config.js b/app/code/Magento/Sales/view/frontend/requirejs-config.js index 6eac516dda45a..cad9609518dc2 100644 --- a/app/code/Magento/Sales/view/frontend/requirejs-config.js +++ b/app/code/Magento/Sales/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -10,4 +10,4 @@ var config = { ordersReturns: 'Magento_Sales/orders-returns' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Sales/view/frontend/templates/email/creditmemo/items.phtml b/app/code/Magento/Sales/view/frontend/templates/email/creditmemo/items.phtml index 4deb9442075dc..753a16e10719f 100644 --- a/app/code/Magento/Sales/view/frontend/templates/email/creditmemo/items.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/email/creditmemo/items.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml index b5247dffc9d47..3e19f6025ac50 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml @@ -1,6 +1,6 @@ + getChildHtml('extra.column.header');?> @@ -28,6 +29,11 @@ + getChildBlock('extra.container'); ?> + + setOrder($_order); ?> + getChildHtml() ?> + @@ -36,7 +42,10 @@ helper('Magento\Sales\Helper\Reorder')->canReorder($_order->getEntityId())) : ?> - + diff --git a/app/code/Magento/Sales/view/frontend/templates/order/info.phtml b/app/code/Magento/Sales/view/frontend/templates/order/info.phtml index d17f9ee0e2748..b187654c41b9b 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/info.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/info.phtml @@ -1,6 +1,6 @@ getOrder() ?> helper('Magento\Sales\Helper\Reorder')->canReorder($_order->getEntityId())) : ?> - + diff --git a/app/code/Magento/Sales/view/frontend/templates/order/info/buttons/rss.phtml b/app/code/Magento/Sales/view/frontend/templates/order/info/buttons/rss.phtml index 6c4190ea05d27..206738a521cba 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/info/buttons/rss.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/info/buttons/rss.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml b/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml index 74a2bbef64501..a47c2f67f109e 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml b/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml index 51241f164b874..0a1785451331a 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml @@ -1,6 +1,6 @@ helper('Magento\Sales\Helper\Reorder')->canReorder($_order->getEntityId())) : ?> - + diff --git a/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml b/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml index 018234040eeea..af043152005b0 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml @@ -1,6 +1,6 @@ " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/app/code/Magento/SalesInventory/LICENSE_AFL.txt b/app/code/Magento/SalesInventory/LICENSE_AFL.txt new file mode 100644 index 0000000000000..f39d641b18a19 --- /dev/null +++ b/app/code/Magento/SalesInventory/LICENSE_AFL.txt @@ -0,0 +1,48 @@ + +Academic Free License ("AFL") v. 3.0 + +This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: + +Licensed under the Academic Free License version 3.0 + + 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + + 1. to reproduce the Original Work in copies, either alone or as part of a collective work; + + 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + + 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; + + 4. to perform the Original Work publicly; and + + 5. to display the Original Work publicly. + + 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + + 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + + 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + + 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + + 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + + 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + + 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + + 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + + 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + + 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + + 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + + 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + + 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + + 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. diff --git a/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php b/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php new file mode 100644 index 0000000000000..6d487307bbb42 --- /dev/null +++ b/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php @@ -0,0 +1,156 @@ +stockManagement = $stockManagement; + $this->stockIndexerProcessor = $stockIndexer; + $this->priceIndexer = $priceIndexer; + $this->creditmemoRepository = $creditmemoRepository; + $this->storeManager = $storeManager; + $this->orderRepository = $orderRepository; + $this->orderItemRepository = $orderItemRepository; + } + + /** + * @param CreditmemoInterface $creditmemo + * @param OrderInterface $order + * @param array $returnToStockItems + * @return void + */ + public function execute( + CreditmemoInterface $creditmemo, + OrderInterface $order, + array $returnToStockItems = [] + ) { + $itemsToUpdate = []; + foreach ($creditmemo->getItems() as $item) { + $qty = $item->getQty(); + $productId = $item->getProductId(); + $orderItem = $this->orderItemRepository->get($item->getOrderItemId()); + $parentItemId = $orderItem->getParentItemId(); + if ($this->canReturnItem($item, $qty, $parentItemId, $returnToStockItems)) { + $parentItem = $parentItemId ? $this->getItemByOrderId($creditmemo, $parentItemId) : false; + $qty = $parentItem ? $parentItem->getQty() * $qty : $qty; + if (isset($itemsToUpdate[$productId])) { + $itemsToUpdate[$productId] += $qty; + } else { + $itemsToUpdate[$productId] = $qty; + } + } + } + + if (!empty($itemsToUpdate)) { + $store = $this->storeManager->getStore($order->getStoreId()); + foreach ($itemsToUpdate as $productId => $qty) { + $this->stockManagement->backItemQty( + $productId, + $qty, + $store->getWebsiteId() + ); + } + + $updatedItemIds = array_keys($itemsToUpdate); + $this->stockIndexerProcessor->reindexList($updatedItemIds); + $this->priceIndexer->reindexList($updatedItemIds); + } + } + + /** + * @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo + * @param int $parentItemId + * @return bool|CreditmemoItemInterface + */ + private function getItemByOrderId(\Magento\Sales\Api\Data\CreditmemoInterface $creditmemo, $parentItemId) + { + foreach ($creditmemo->getItems() as $item) { + if ($item->getOrderItemId() == $parentItemId) { + return $item; + } + } + return false; + } + + /** + * @param \Magento\Sales\Api\Data\CreditmemoItemInterface $item + * @param int $qty + * @param int[] $returnToStockItems + * @param int $parentItemId + * @return bool + */ + private function canReturnItem( + \Magento\Sales\Api\Data\CreditmemoItemInterface $item, + $qty, + $parentItemId = null, + array $returnToStockItems = [] + ) { + return (in_array($item->getOrderItemId(), $returnToStockItems) || in_array($parentItemId, $returnToStockItems)) + && $qty; + } +} diff --git a/app/code/Magento/SalesInventory/Model/Order/ReturnValidator.php b/app/code/Magento/SalesInventory/Model/Order/ReturnValidator.php new file mode 100644 index 0000000000000..65db325509fdc --- /dev/null +++ b/app/code/Magento/SalesInventory/Model/Order/ReturnValidator.php @@ -0,0 +1,70 @@ +orderItemRepository = $orderItemRepository; + } + + /** + * @param int[] $returnToStockItems + * @param CreditmemoInterface $creditmemo + * @return \Magento\Framework\Phrase|null + */ + public function validate($returnToStockItems, CreditmemoInterface $creditmemo) + { + $creditmemoItems = $creditmemo->getItems(); + + /** @var int $item */ + foreach ($returnToStockItems as $item) { + try { + $orderItem = $this->orderItemRepository->get($item); + if (!$this->isOrderItemPartOfCreditmemo($creditmemoItems, $orderItem)) { + return __('The "%1" product is not part of the current creditmemo.', $orderItem->getSku()); + } + } catch (NoSuchEntityException $e) { + return __('The return to stock argument contains product item that is not part of the original order.'); + } + } + return null; + } + + /** + * @param CreditmemoItemInterface[] $creditmemoItems + * @param OrderItemInterface $orderItem + * @return bool + */ + private function isOrderItemPartOfCreditmemo(array $creditmemoItems, OrderItemInterface $orderItem) + { + foreach ($creditmemoItems as $creditmemoItem) { + if ($creditmemoItem->getOrderItemId() == $orderItem->getItemId()) { + return true; + } + } + return false; + } +} diff --git a/app/code/Magento/SalesInventory/Model/Plugin/Order/ReturnToStockInvoice.php b/app/code/Magento/SalesInventory/Model/Plugin/Order/ReturnToStockInvoice.php new file mode 100644 index 0000000000000..da80ef1a14f26 --- /dev/null +++ b/app/code/Magento/SalesInventory/Model/Plugin/Order/ReturnToStockInvoice.php @@ -0,0 +1,105 @@ +returnProcessor = $returnProcessor; + $this->creditmemoRepository = $creditmemoRepository; + $this->orderRepository = $orderRepository; + $this->invoiceRepository = $invoiceRepository; + $this->stockConfiguration = $stockConfiguration; + } + + /** + * @param \Magento\Sales\Api\RefundInvoiceInterface $refundService + * @param \Closure $proceed + * @param int $invoiceId + * @param \Magento\Sales\Api\Data\CreditmemoItemCreationInterface[] $items + * @param bool|null $isOnline + * @param bool|null $notify + * @param bool|null $appendComment + * @param \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface|null $comment + * @param \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface|null $arguments + * @return int + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundExecute( + \Magento\Sales\Api\RefundInvoiceInterface $refundService, + \Closure $proceed, + $invoiceId, + array $items = [], + $isOnline = false, + $notify = false, + $appendComment = false, + \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null, + \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null + ) { + $resultEntityId = $proceed($invoiceId, $items, $isOnline, $notify, $appendComment, $comment, $arguments); + if ($this->stockConfiguration->isAutoReturnEnabled()) { + return $resultEntityId; + } + + $invoice = $this->invoiceRepository->get($invoiceId); + $order = $this->orderRepository->get($invoice->getOrderId()); + + $returnToStockItems = []; + if ($arguments !== null + && $arguments->getExtensionAttributes() !== null + && $arguments->getExtensionAttributes()->getReturnToStockItems() !== null + ) { + $returnToStockItems = $arguments->getExtensionAttributes()->getReturnToStockItems(); + } + + $creditmemo = $this->creditmemoRepository->get($resultEntityId); + $this->returnProcessor->execute($creditmemo, $order, $returnToStockItems); + + return $resultEntityId; + } +} diff --git a/app/code/Magento/SalesInventory/Model/Plugin/Order/ReturnToStockOrder.php b/app/code/Magento/SalesInventory/Model/Plugin/Order/ReturnToStockOrder.php new file mode 100644 index 0000000000000..ce38f071e071f --- /dev/null +++ b/app/code/Magento/SalesInventory/Model/Plugin/Order/ReturnToStockOrder.php @@ -0,0 +1,101 @@ +returnProcessor = $returnProcessor; + $this->creditmemoRepository = $creditmemoRepository; + $this->orderRepository = $orderRepository; + $this->stockConfiguration = $stockConfiguration; + } + + /** + * @param RefundOrderInterface $refundService + * @param \Closure $proceed + * @param int $orderId + * @param \Magento\Sales\Api\Data\CreditmemoItemCreationInterface[] $items + * @param bool|null $notify + * @param bool|null $appendComment + * @param \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface|null $comment + * @param \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface|null $arguments + * @return int + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundExecute( + RefundOrderInterface $refundService, + \Closure $proceed, + $orderId, + array $items = [], + $notify = false, + $appendComment = false, + \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null, + \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null + ) { + $resultEntityId = $proceed($orderId, $items, $notify, $appendComment, $comment,$arguments); + if ($this->stockConfiguration->isAutoReturnEnabled()) { + return $resultEntityId; + } + + $order = $this->orderRepository->get($orderId); + + $returnToStockItems = []; + if ($arguments !== null + && $arguments->getExtensionAttributes() !== null + && $arguments->getExtensionAttributes()->getReturnToStockItems() !== null + ) { + $returnToStockItems = $arguments->getExtensionAttributes()->getReturnToStockItems(); + } + + $creditmemo = $this->creditmemoRepository->get($resultEntityId); + $this->returnProcessor->execute($creditmemo, $order, $returnToStockItems); + + return $resultEntityId; + } +} diff --git a/app/code/Magento/SalesInventory/Model/Plugin/Order/Validation/InvoiceRefundCreationArguments.php b/app/code/Magento/SalesInventory/Model/Plugin/Order/Validation/InvoiceRefundCreationArguments.php new file mode 100644 index 0000000000000..2f09ccb7b856a --- /dev/null +++ b/app/code/Magento/SalesInventory/Model/Plugin/Order/Validation/InvoiceRefundCreationArguments.php @@ -0,0 +1,100 @@ +returnValidator = $returnValidator; + } + + /** + * @param RefundInvoiceInterface $refundInvoiceValidator + * @param \Closure $proceed + * @param InvoiceInterface $invoice + * @param OrderInterface $order + * @param CreditmemoInterface $creditmemo + * @param array $items + * @param bool $isOnline + * @param bool $notify + * @param bool $appendComment + * @param \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface|null $comment + * @param \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface|null $arguments + * @return ValidatorResultInterface + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function aroundValidate( + RefundInvoiceInterface $refundInvoiceValidator, + \Closure $proceed, + InvoiceInterface $invoice, + OrderInterface $order, + CreditmemoInterface $creditmemo, + array $items = [], + $isOnline = false, + $notify = false, + $appendComment = false, + \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null, + \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null + ) { + $validationResults = $proceed( + $invoice, + $order, + $creditmemo, + $items, + $isOnline, + $notify, + $appendComment, + $comment, + $arguments + ); + if ($this->isReturnToStockItems($arguments)) { + return $validationResults; + } + + /** @var int[] $returnToStockItems */ + $returnToStockItems = $arguments->getExtensionAttributes()->getReturnToStockItems(); + $validationMessage = $this->returnValidator->validate($returnToStockItems, $creditmemo); + if ($validationMessage) { + $validationResults->addMessage($validationMessage); + } + + return $validationResults; + } + + /** + * @param CreditmemoCreationArgumentsInterface|null $arguments + * @return bool + */ + private function isReturnToStockItems($arguments) + { + return $arguments === null + || $arguments->getExtensionAttributes() === null + || $arguments->getExtensionAttributes()->getReturnToStockItems() === null; + } +} diff --git a/app/code/Magento/SalesInventory/Model/Plugin/Order/Validation/OrderRefundCreationArguments.php b/app/code/Magento/SalesInventory/Model/Plugin/Order/Validation/OrderRefundCreationArguments.php new file mode 100644 index 0000000000000..79fa2395cba8d --- /dev/null +++ b/app/code/Magento/SalesInventory/Model/Plugin/Order/Validation/OrderRefundCreationArguments.php @@ -0,0 +1,84 @@ +returnValidator = $returnValidator; + } + + /** + * @param RefundOrderInterface $refundOrderValidator + * @param \Closure $proceed + * @param OrderInterface $order + * @param CreditmemoInterface $creditmemo + * @param array $items + * @param bool $notify + * @param bool $appendComment + * @param CreditmemoCommentCreationInterface|null $comment + * @param CreditmemoCreationArgumentsInterface|null $arguments + * @return ValidatorResultInterface + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundValidate( + RefundOrderInterface $refundOrderValidator, + \Closure $proceed, + OrderInterface $order, + CreditmemoInterface $creditmemo, + array $items = [], + $notify = false, + $appendComment = false, + CreditmemoCommentCreationInterface $comment = null, + CreditmemoCreationArgumentsInterface $arguments = null + ) { + $validationResults = $proceed($order, $creditmemo, $items, $notify, $appendComment, $comment, $arguments); + if ($this->isReturnToStockItems($arguments)) { + return $validationResults; + } + + $returnToStockItems = $arguments->getExtensionAttributes()->getReturnToStockItems(); + $validationMessage = $this->returnValidator->validate($returnToStockItems, $creditmemo); + if ($validationMessage) { + $validationResults->addMessage($validationMessage); + } + + return $validationResults; + } + + /** + * @param CreditmemoCreationArgumentsInterface|null $arguments + * @return bool + */ + private function isReturnToStockItems($arguments) + { + return $arguments === null + || $arguments->getExtensionAttributes() === null + || $arguments->getExtensionAttributes()->getReturnToStockItems() === null; + } +} diff --git a/app/code/Magento/SalesInventory/README.md b/app/code/Magento/SalesInventory/README.md new file mode 100644 index 0000000000000..915569ddd3ce2 --- /dev/null +++ b/app/code/Magento/SalesInventory/README.md @@ -0,0 +1 @@ +Magento_SalesInventory module allows retrieve and update stock attributes related to Magento_Sales, such as status and quantity. diff --git a/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnProcessorTest.php b/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnProcessorTest.php new file mode 100644 index 0000000000000..6f339031785e1 --- /dev/null +++ b/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnProcessorTest.php @@ -0,0 +1,195 @@ +stockManagementMock = $this->getMockBuilder(StockManagementInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stockIndexerProcessorMock = $this->getMockBuilder( + \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class + )->disableOriginalConstructor() + ->getMock(); + $this->priceIndexerMock = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Price\Processor::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoRepositoryMock = $this->getMockBuilder(CreditmemoRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderItemRepositoryMock = $this->getMockBuilder(OrderItemRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderMock = $this->getMockBuilder(OrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoMock = $this->getMockBuilder(CreditmemoInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoItemMock = $this->getMockBuilder(CreditmemoItemInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderItemMock = $this->getMockBuilder(OrderItemInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeMock = $this->getMockBuilder(StoreInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->returnProcessor = new ReturnProcessor( + $this->stockManagementMock, + $this->stockIndexerProcessorMock, + $this->priceIndexerMock, + $this->creditmemoRepositoryMock, + $this->storeManagerMock, + $this->orderRepositoryMock, + $this->orderItemRepositoryMock + ); + } + + public function testExecute() + { + $orderItemId = 99; + $productId = 50; + $returnToStockItems = [$orderItemId]; + $qty = 1; + $storeId = 0; + $webSiteId = 10; + + $this->creditmemoMock->expects($this->once()) + ->method('getItems') + ->willReturn([$this->creditmemoItemMock]); + + $this->creditmemoItemMock->expects($this->once()) + ->method('getQty') + ->willReturn($qty); + + $this->creditmemoItemMock->expects($this->exactly(2)) + ->method('getOrderItemId') + ->willReturn($orderItemId); + + $this->creditmemoItemMock->expects($this->once()) + ->method('getProductId') + ->willReturn($productId); + + $this->orderItemRepositoryMock->expects($this->once()) + ->method('get') + ->with($orderItemId) + ->willReturn($this->orderItemMock); + + $this->orderMock->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + + $this->storeManagerMock->expects($this->once()) + ->method('getStore') + ->with($storeId) + ->willReturn($this->storeMock); + + $this->storeMock->expects($this->once()) + ->method('getWebsiteId') + ->willReturn($webSiteId); + + $this->stockManagementMock->expects($this->once()) + ->method('backItemQty') + ->with($productId, $qty, $webSiteId) + ->willReturn(true); + + $this->stockIndexerProcessorMock->expects($this->once()) + ->method('reindexList') + ->with([$productId]); + + $this->priceIndexerMock->expects($this->once()) + ->method('reindexList') + ->with([$productId]); + + $this->returnProcessor->execute($this->creditmemoMock, $this->orderMock, $returnToStockItems); + } +} diff --git a/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnValidatorTest.php b/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnValidatorTest.php new file mode 100644 index 0000000000000..52a00241054a5 --- /dev/null +++ b/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnValidatorTest.php @@ -0,0 +1,134 @@ +orderItemRepositoryMock = $this->getMockBuilder(OrderItemRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->creditMemoMock = $this->getMockBuilder(CreditmemoInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->creditMemoItemMock = $this->getMockBuilder(CreditmemoItemInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderItemMock = $this->getMockBuilder(OrderItemInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->returnValidator = new ReturnValidator( + $this->orderItemRepositoryMock + ); + } + + /** + * @dataProvider dataProvider + */ + public function testValidate( + $expectedResult, + $returnToStockItems, + $orderItemId, + $creditMemoItemId, + $productSku = null + ) { + $this->creditMemoMock->expects($this->once()) + ->method('getItems') + ->willReturn([$this->creditMemoItemMock]); + + $this->orderItemRepositoryMock->expects($this->once()) + ->method('get') + ->with($returnToStockItems[0]) + ->willReturn($this->orderItemMock); + + $this->orderItemMock->expects($this->once()) + ->method('getItemId') + ->willReturn($orderItemId); + + $this->creditMemoItemMock->expects($this->once()) + ->method('getOrderItemId') + ->willReturn($creditMemoItemId); + + if ($productSku) { + $this->orderItemMock->expects($this->once()) + ->method('getSku') + ->willReturn($productSku); + } + + $this->assertEquals( + $this->returnValidator->validate($returnToStockItems, $this->creditMemoMock), + $expectedResult + ); + } + + public function testValidationWithWrongOrderItems() + { + $returnToStockItems = [1]; + $this->creditMemoMock->expects($this->once()) + ->method('getItems') + ->willReturn([$this->creditMemoItemMock]); + $this->orderItemRepositoryMock->expects($this->once()) + ->method('get') + ->with($returnToStockItems[0]) + ->willThrowException(new NoSuchEntityException); + + $this->assertEquals( + $this->returnValidator->validate($returnToStockItems, $this->creditMemoMock), + __('The return to stock argument contains product item that is not part of the original order.') + ); + + } + + public function dataProvider() + { + return [ + 'PostirivValidationTest' => [null, [1], 1, 1], + 'WithWrongReturnToStockItems' => [ + __('The "%1" product is not part of the current creditmemo.', 'sku1'), [2], 2, 1, 'sku1', + ], + ]; + } +} diff --git a/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/ReturnToStockInvoiceTest.php b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/ReturnToStockInvoiceTest.php new file mode 100644 index 0000000000000..535372d65403c --- /dev/null +++ b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/ReturnToStockInvoiceTest.php @@ -0,0 +1,188 @@ +returnProcessorMock = $this->getMockBuilder(\Magento\SalesInventory\Model\Order\ReturnProcessor::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoRepositoryMock = $this->getMockBuilder(\Magento\Sales\Api\CreditmemoRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderRepositoryMock = $this->getMockBuilder(\Magento\Sales\Api\OrderRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->invoiceRepositoryMock = $this->getMockBuilder(\Magento\Sales\Api\InvoiceRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->refundInvoiceMock = $this->getMockBuilder(\Magento\Sales\Api\RefundInvoiceInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoCreationArgumentsMock = $this->getMockBuilder( + \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface::class + )->disableOriginalConstructor() + ->getMock(); + $this->extensionAttributesMock = $this->getMockBuilder( + \Magento\Sales\Api\Data\CreditmemoCreationArgumentsExtensionInterface::class + )->disableOriginalConstructor() + ->setMethods(['getReturnToStockItems']) + ->getMock(); + $this->orderMock = $this->getMockBuilder(\Magento\Sales\Api\Data\OrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoMock = $this->getMockBuilder(\Magento\Sales\Api\Data\CreditmemoInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->invoiceMock = $this->getMockBuilder(\Magento\Sales\Api\Data\InvoiceInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stockConfigurationMock = $this->getMockBuilder( + \Magento\CatalogInventory\Api\StockConfigurationInterface::class + )->disableOriginalConstructor() + ->getMock(); + + $this->returnToStock = new \Magento\SalesInventory\Model\Plugin\Order\ReturnToStockInvoice( + $this->returnProcessorMock, + $this->creditmemoRepositoryMock, + $this->orderRepositoryMock, + $this->invoiceRepositoryMock, + $this->stockConfigurationMock + ); + } + + public function testAroundExecute() + { + $orderId = 1; + $creditmemoId = 99; + $items = []; + $returnToStockItems = [1]; + $invoiceId = 98; + + $this->proceed = function () use ($creditmemoId) { + return $creditmemoId; + }; + $this->creditmemoCreationArgumentsMock->expects($this->exactly(3)) + ->method('getExtensionAttributes') + ->willReturn($this->extensionAttributesMock); + + $this->invoiceRepositoryMock->expects($this->once()) + ->method('get') + ->with($invoiceId) + ->willReturn($this->invoiceMock); + + $this->extensionAttributesMock->expects($this->exactly(2)) + ->method('getReturnToStockItems') + ->willReturn($returnToStockItems); + + $this->orderRepositoryMock->expects($this->once()) + ->method('get') + ->with($orderId) + ->willReturn($this->orderMock); + + $this->creditmemoRepositoryMock->expects($this->once()) + ->method('get') + ->with($creditmemoId) + ->willReturn($this->creditmemoMock); + + $this->returnProcessorMock->expects($this->once()) + ->method('execute') + ->with($this->creditmemoMock, $this->orderMock, $returnToStockItems); + + $this->invoiceMock->expects($this->once()) + ->method('getOrderId') + ->willReturn($orderId); + + $this->stockConfigurationMock->expects($this->once()) + ->method('isAutoReturnEnabled') + ->willReturn(false); + + $this->assertEquals( + $this->returnToStock->aroundExecute( + $this->refundInvoiceMock, + $this->proceed, + $invoiceId, + $items, + false, + false, + false, + null, + $this->creditmemoCreationArgumentsMock + ), + $creditmemoId + ); + } +} diff --git a/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/ReturnToStockOrderTest.php b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/ReturnToStockOrderTest.php new file mode 100644 index 0000000000000..de50f42e08caa --- /dev/null +++ b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/ReturnToStockOrderTest.php @@ -0,0 +1,166 @@ +returnProcessorMock = $this->getMockBuilder(ReturnProcessor::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoRepositoryMock = $this->getMockBuilder(CreditmemoRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->refundOrderMock = $this->getMockBuilder(RefundOrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoCreationArgumentsMock = $this->getMockBuilder(CreditmemoCreationArgumentsInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->extensionAttributesMock = $this->getMockBuilder(CreditmemoCreationArgumentsExtensionInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getReturnToStockItems']) + ->getMock(); + $this->orderMock = $this->getMockBuilder(OrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->creditmemoMock = $this->getMockBuilder(CreditmemoInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->returnToStock = new ReturnToStockOrder( + $this->returnProcessorMock, + $this->creditmemoRepositoryMock, + $this->orderRepositoryMock, + $this->stockConfigurationMock + ); + } + + public function testAroundExecute() + { + $orderId = 1; + $creditmemoId = 99; + $items = []; + $returnToStockItems = [1]; + $this->proceed = function () use ($creditmemoId) { + return $creditmemoId; + }; + $this->creditmemoCreationArgumentsMock->expects($this->exactly(3)) + ->method('getExtensionAttributes') + ->willReturn($this->extensionAttributesMock); + + $this->extensionAttributesMock->expects($this->exactly(2)) + ->method('getReturnToStockItems') + ->willReturn($returnToStockItems); + + $this->orderRepositoryMock->expects($this->once()) + ->method('get') + ->with($orderId) + ->willReturn($this->orderMock); + + $this->creditmemoRepositoryMock->expects($this->once()) + ->method('get') + ->with($creditmemoId) + ->willReturn($this->creditmemoMock); + + $this->returnProcessorMock->expects($this->once()) + ->method('execute') + ->with($this->creditmemoMock, $this->orderMock, $returnToStockItems); + + $this->stockConfigurationMock->expects($this->once()) + ->method('isAutoReturnEnabled') + ->willReturn(false); + + $this->assertEquals( + $this->returnToStock->aroundExecute( + $this->refundOrderMock, + $this->proceed, + $orderId, + $items, + false, + false, + null, + $this->creditmemoCreationArgumentsMock + ), + $creditmemoId + ); + } +} diff --git a/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/Validation/InvoiceRefundCreationArgumentsTest.php b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/Validation/InvoiceRefundCreationArgumentsTest.php new file mode 100644 index 0000000000000..21c0025d32fb0 --- /dev/null +++ b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/Validation/InvoiceRefundCreationArgumentsTest.php @@ -0,0 +1,158 @@ +returnValidatorMock = $this->getMockBuilder(ReturnValidator::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->creditmemoCreationArgumentsMock = $this->getMockBuilder(CreditmemoCreationArgumentsInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->extensionAttributesMock = $this->getMockBuilder(CreditmemoCreationArgumentsExtensionInterface::class) + ->setMethods(['getReturnToStockItems']) + ->disableOriginalConstructor() + ->getMock(); + + $this->validateResultMock = $this->getMockBuilder(ValidatorResultInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->refundInvoiceValidatorMock = $this->getMockBuilder(RefundInvoiceInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->invoiceMock = $this->getMockBuilder(InvoiceInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderMock = $this->getMockBuilder(OrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->creditmemoMock = $this->getMockBuilder(CreditmemoInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->proceed = function () { + return $this->validateResultMock; + }; + $this->plugin = new InvoiceRefundCreationArguments($this->returnValidatorMock); + } + + /** + * @dataProvider dataProvider + */ + public function testAroundValidation($errorMessage) + { + $returnToStockItems = [1]; + $this->creditmemoCreationArgumentsMock->expects($this->exactly(3)) + ->method('getExtensionAttributes') + ->willReturn($this->extensionAttributesMock); + + $this->extensionAttributesMock->expects($this->exactly(2)) + ->method('getReturnToStockItems') + ->willReturn($returnToStockItems); + + $this->returnValidatorMock->expects($this->once()) + ->method('validate') + ->willReturn($errorMessage); + + $this->validateResultMock->expects($errorMessage ? $this->once() : $this->never()) + ->method('addMessage') + ->with($errorMessage); + + $this->plugin->aroundValidate( + $this->refundInvoiceValidatorMock, + $this->proceed, + $this->invoiceMock, + $this->orderMock, + $this->creditmemoMock, + [], + false, + false, + false, + null, + $this->creditmemoCreationArgumentsMock + ); + } + + public function dataProvider() + { + return [ + 'withErrors' => ['Error!'], + 'withoutErrors' => ['null'], + ]; + } +} diff --git a/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/Validation/OrderRefundCreationArgumentsTest.php b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/Validation/OrderRefundCreationArgumentsTest.php new file mode 100644 index 0000000000000..6e9358d3ef7f0 --- /dev/null +++ b/app/code/Magento/SalesInventory/Test/Unit/Model/Plugin/Order/Validation/OrderRefundCreationArgumentsTest.php @@ -0,0 +1,151 @@ +returnValidatorMock = $this->getMockBuilder(ReturnValidator::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->creditmemoCreationArgumentsMock = $this->getMockBuilder(CreditmemoCreationArgumentsInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->extensionAttributesMock = $this->getMockBuilder(CreditmemoCreationArgumentsExtensionInterface::class) + ->setMethods(['getReturnToStockItems']) + ->disableOriginalConstructor() + ->getMock(); + + $this->validateResultMock = $this->getMockBuilder(ValidatorResultInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->refundOrderValidatorMock = $this->getMockBuilder(RefundOrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderMock = $this->getMockBuilder(OrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->creditmemoMock = $this->getMockBuilder(CreditmemoInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->proceed = function () { + return $this->validateResultMock; + }; + + $this->plugin = new OrderRefundCreationArguments($this->returnValidatorMock); + } + + /** + * @dataProvider dataProvider + */ + public function testAroundValidation($errorMessage) + { + $returnToStockItems = [1]; + $this->creditmemoCreationArgumentsMock->expects($this->exactly(3)) + ->method('getExtensionAttributes') + ->willReturn($this->extensionAttributesMock); + + $this->extensionAttributesMock->expects($this->exactly(2)) + ->method('getReturnToStockItems') + ->willReturn($returnToStockItems); + + $this->returnValidatorMock->expects($this->once()) + ->method('validate') + ->willReturn($errorMessage); + + $this->validateResultMock->expects($errorMessage ? $this->once() : $this->never()) + ->method('addMessage') + ->with($errorMessage); + + $this->plugin->aroundValidate( + $this->refundOrderValidatorMock, + $this->proceed, + $this->orderMock, + $this->creditmemoMock, + [], + false, + false, + null, + $this->creditmemoCreationArgumentsMock + ); + } + + /** + * @return array + */ + public function dataProvider() + { + return [ + 'withErrors' => ['Error!'], + 'withoutErrors' => ['null'], + ]; + } +} diff --git a/app/code/Magento/SalesInventory/composer.json b/app/code/Magento/SalesInventory/composer.json new file mode 100644 index 0000000000000..783382f0d4af6 --- /dev/null +++ b/app/code/Magento/SalesInventory/composer.json @@ -0,0 +1,26 @@ +{ + "name": "magento/module-sales-inventory", + "description": "N/A", + "require": { + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", + "magento/module-catalog-inventory": "100.1.*", + "magento/module-sales": "100.1.*", + "magento/module-store": "100.1.*", + "magento/module-catalog": "101.0.*", + "magento/framework": "100.1.*" + }, + "type": "magento2-module", + "version": "100.1.1", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\SalesInventory\\": "" + } + } +} diff --git a/app/code/Magento/SalesInventory/etc/di.xml b/app/code/Magento/SalesInventory/etc/di.xml new file mode 100644 index 0000000000000..bf91a0dc50b33 --- /dev/null +++ b/app/code/Magento/SalesInventory/etc/di.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/SalesInventory/etc/extension_attributes.xml b/app/code/Magento/SalesInventory/etc/extension_attributes.xml new file mode 100644 index 0000000000000..481f13cfeae32 --- /dev/null +++ b/app/code/Magento/SalesInventory/etc/extension_attributes.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/app/code/Magento/SalesInventory/etc/module.xml b/app/code/Magento/SalesInventory/etc/module.xml new file mode 100644 index 0000000000000..4aa89e151a35e --- /dev/null +++ b/app/code/Magento/SalesInventory/etc/module.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/app/code/Magento/SalesInventory/registration.php b/app/code/Magento/SalesInventory/registration.php new file mode 100644 index 0000000000000..92743627b5bc2 --- /dev/null +++ b/app/code/Magento/SalesInventory/registration.php @@ -0,0 +1,11 @@ +getActionsFieldSetId($formName); $newChildUrl = $this->getUrl( - 'sales_rule/promo_quote/newActionHtml/form/rule_actions_fieldset_' . $actionsFieldSetId, + 'sales_rule/promo_quote/newActionHtml/form/' . $actionsFieldSetId, ['form_namespace' => $formName] ); diff --git a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Conditions.php b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Conditions.php index 365c617345d60..dbf237e405c28 100644 --- a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Conditions.php +++ b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Conditions.php @@ -1,6 +1,6 @@ _redirect('sales_rule/*'); return; } + $model->getConditions()->setFormName('sales_rule_form'); + $model->getConditions()->setJsFormObject( + $model->getConditionsFieldSetId($model->getConditions()->getFormName()) + ); + $model->getActions()->setFormName('sales_rule_form'); + $model->getActions()->setJsFormObject( + $model->getActionsFieldSetId($model->getActions()->getFormName()) + ); $resultPage->getLayout()->getBlock('promo_sales_rule_edit_tab_coupons')->setCanShow(true); } @@ -65,15 +73,6 @@ public function execute() $model->addData($data); } - $model->getConditions()->setFormName('sales_rule_form'); - $model->getConditions()->setJsFormObject( - $model->getConditionsFieldSetId($model->getConditions()->getFormName()) - ); - $model->getActions()->setFormName('sales_rule_form'); - $model->getActions()->setJsFormObject( - $model->getActionsFieldSetId($model->getActions()->getFormName()) - ); - $this->_initAction(); $this->_addBreadcrumb($id ? __('Edit Rule') : __('New Rule'), $id ? __('Edit Rule') : __('New Rule')); diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/ExportCouponsCsv.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/ExportCouponsCsv.php index 70d2936e851ed..98bd935b9b6cd 100644 --- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/ExportCouponsCsv.php +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/ExportCouponsCsv.php @@ -1,7 +1,7 @@ getRequest()->getParam('id'); - $formName = $this->getRequest()->getParam('form_namespace'); + $formName = $this->getRequest()->getParam('form'); $typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type'))); $type = $typeArr[0]; diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php index 892c2ea3cdb29..b9723d6697059 100644 --- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php @@ -1,7 +1,7 @@ quoteInto( + 'main_table.coupon_type = ? ', + \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON + ); + $orWhereConditions = [ - $connection->quoteInto( - 'main_table.coupon_type = ? ', - \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON - ), $connection->quoteInto( '(main_table.coupon_type = ? AND rule_coupons.type = 0)', \Magento\SalesRule\Model\Rule::COUPON_TYPE_AUTO @@ -186,7 +185,9 @@ public function setValidationFilter( $orWhereCondition = implode(' OR ', $orWhereConditions); $andWhereCondition = implode(' AND ', $andWhereConditions); - $select->where('(' . $orWhereCondition . ') AND ' . $andWhereCondition); + $select->where( + $noCouponWhereCondition . ' OR ((' . $orWhereCondition . ') AND ' . $andWhereCondition . ')' + ); } else { $this->addFieldToFilter( 'main_table.coupon_type', @@ -214,7 +215,7 @@ public function setValidationFilter( public function addWebsiteGroupDateFilter($websiteId, $customerGroupId, $now = null) { if (!$this->getFlag('website_group_date_filter')) { - if (is_null($now)) { + if ($now === null) { $now = $this->_date->date()->format('Y-m-d'); } @@ -277,7 +278,11 @@ public function addAttributeInConditionFilter($attributeCode) $field = $this->_getMappedField('actions_serialized'); $aCond = $this->_getConditionSql($field, ['like' => $match]); - $this->getSelect()->where(sprintf('(%s OR %s)', $cCond, $aCond), null, \Magento\Framework\DB\Select::TYPE_CONDITION); + $this->getSelect()->where( + sprintf('(%s OR %s)', $cCond, $aCond), + null, + \Magento\Framework\DB\Select::TYPE_CONDITION + ); return $this; } diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Customer.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Customer.php index 9798d90c98b0a..ac54ea3574152 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Customer.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule/Customer.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/SalesRule/etc/adminhtml/di.xml b/app/code/Magento/SalesRule/etc/adminhtml/di.xml index 725c276a01e01..2ff711c3c66ba 100644 --- a/app/code/Magento/SalesRule/etc/adminhtml/di.xml +++ b/app/code/Magento/SalesRule/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/adminhtml/events.xml b/app/code/Magento/SalesRule/etc/adminhtml/events.xml index 7be70531a9bc9..6e60ea28a90a6 100644 --- a/app/code/Magento/SalesRule/etc/adminhtml/events.xml +++ b/app/code/Magento/SalesRule/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/adminhtml/menu.xml b/app/code/Magento/SalesRule/etc/adminhtml/menu.xml index b80e188061695..f212fbf97ba92 100644 --- a/app/code/Magento/SalesRule/etc/adminhtml/menu.xml +++ b/app/code/Magento/SalesRule/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/adminhtml/routes.xml b/app/code/Magento/SalesRule/etc/adminhtml/routes.xml index a48544d4176a3..a0fdf183fb749 100644 --- a/app/code/Magento/SalesRule/etc/adminhtml/routes.xml +++ b/app/code/Magento/SalesRule/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/adminhtml/system.xml b/app/code/Magento/SalesRule/etc/adminhtml/system.xml index 03cb3d1effffd..b3f0c4d82d3d5 100644 --- a/app/code/Magento/SalesRule/etc/adminhtml/system.xml +++ b/app/code/Magento/SalesRule/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/config.xml b/app/code/Magento/SalesRule/etc/config.xml index 8eae13783b9b3..d80a9033569a9 100644 --- a/app/code/Magento/SalesRule/etc/config.xml +++ b/app/code/Magento/SalesRule/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/crontab.xml b/app/code/Magento/SalesRule/etc/crontab.xml index 9f8d7a760154d..b3914c6a7145a 100644 --- a/app/code/Magento/SalesRule/etc/crontab.xml +++ b/app/code/Magento/SalesRule/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/di.xml b/app/code/Magento/SalesRule/etc/di.xml index 2c731823b778f..23a00208c7e0c 100644 --- a/app/code/Magento/SalesRule/etc/di.xml +++ b/app/code/Magento/SalesRule/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/events.xml b/app/code/Magento/SalesRule/etc/events.xml index 0100d0427566b..2c34a9f82380a 100644 --- a/app/code/Magento/SalesRule/etc/events.xml +++ b/app/code/Magento/SalesRule/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/fieldset.xml b/app/code/Magento/SalesRule/etc/fieldset.xml index 758bc0cc4910f..ce0478928a6ac 100644 --- a/app/code/Magento/SalesRule/etc/fieldset.xml +++ b/app/code/Magento/SalesRule/etc/fieldset.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/frontend/di.xml b/app/code/Magento/SalesRule/etc/frontend/di.xml index 725c276a01e01..2ff711c3c66ba 100644 --- a/app/code/Magento/SalesRule/etc/frontend/di.xml +++ b/app/code/Magento/SalesRule/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/module.xml b/app/code/Magento/SalesRule/etc/module.xml index d47493733e905..464cb1382346e 100644 --- a/app/code/Magento/SalesRule/etc/module.xml +++ b/app/code/Magento/SalesRule/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/sales.xml b/app/code/Magento/SalesRule/etc/sales.xml index 008a81acf3eea..ad85d8341566a 100644 --- a/app/code/Magento/SalesRule/etc/sales.xml +++ b/app/code/Magento/SalesRule/etc/sales.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/etc/webapi.xml b/app/code/Magento/SalesRule/etc/webapi.xml index b4cb239c244a0..d2ddda8473c37 100644 --- a/app/code/Magento/SalesRule/etc/webapi.xml +++ b/app/code/Magento/SalesRule/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/registration.php b/app/code/Magento/SalesRule/registration.php index 841c8b742e8a8..9b6025463b7a6 100644 --- a/app/code/Magento/SalesRule/registration.php +++ b/app/code/Magento/SalesRule/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_edit.xml b/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_edit.xml index cb284b708c70d..182b535ec9b64 100644 --- a/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_edit.xml +++ b/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml b/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml index fbbf9657f42ac..ee518d69466d7 100644 --- a/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml +++ b/app/code/Magento/SalesRule/view/adminhtml/layout/sales_rule_promo_quote_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/view/adminhtml/templates/promo/salesrulejs.phtml b/app/code/Magento/SalesRule/view/adminhtml/templates/promo/salesrulejs.phtml index d99e5107f1797..bd8f611f770c9 100644 --- a/app/code/Magento/SalesRule/view/adminhtml/templates/promo/salesrulejs.phtml +++ b/app/code/Magento/SalesRule/view/adminhtml/templates/promo/salesrulejs.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/SalesRule/view/adminhtml/templates/tab/coupons.phtml b/app/code/Magento/SalesRule/view/adminhtml/templates/tab/coupons.phtml index ec86e7366cadd..cfd4299fc2299 100644 --- a/app/code/Magento/SalesRule/view/adminhtml/templates/tab/coupons.phtml +++ b/app/code/Magento/SalesRule/view/adminhtml/templates/tab/coupons.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml b/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml index a9a682be3194c..9d937702e7b30 100644 --- a/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml +++ b/app/code/Magento/SalesRule/view/adminhtml/ui_component/sales_rule_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/view/base/web/js/form/element/coupon-type.js b/app/code/Magento/SalesRule/view/base/web/js/form/element/coupon-type.js index ea97b910076ac..798e7a94ac9ac 100644 --- a/app/code/Magento/SalesRule/view/base/web/js/form/element/coupon-type.js +++ b/app/code/Magento/SalesRule/view/base/web/js/form/element/coupon-type.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/SalesRule/view/base/web/js/form/element/manage-coupon-codes.js b/app/code/Magento/SalesRule/view/base/web/js/form/element/manage-coupon-codes.js index 2e4f2defec979..e2c70c75adfdd 100644 --- a/app/code/Magento/SalesRule/view/base/web/js/form/element/manage-coupon-codes.js +++ b/app/code/Magento/SalesRule/view/base/web/js/form/element/manage-coupon-codes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/SalesRule/view/frontend/layout/checkout_cart_index.xml b/app/code/Magento/SalesRule/view/frontend/layout/checkout_cart_index.xml index 79906fc574622..5911249a227ec 100644 --- a/app/code/Magento/SalesRule/view/frontend/layout/checkout_cart_index.xml +++ b/app/code/Magento/SalesRule/view/frontend/layout/checkout_cart_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml index 1f89df6ac84f1..27f0669b4f020 100644 --- a/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/SalesRule/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ @@ -65,4 +65,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js index ed5744feb6ce8..a6bef77fdca3a 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -17,16 +17,20 @@ define( 'mage/storage', 'Magento_Checkout/js/action/get-payment-information', 'Magento_Checkout/js/model/totals', - 'mage/translate' + 'mage/translate', + 'Magento_Checkout/js/model/full-screen-loader' ], - function ($, quote, urlManager, errorProcessor, messageContainer, storage, getPaymentInformationAction, totals, $t) { + function ($, quote, urlManager, errorProcessor, messageContainer, storage, getPaymentInformationAction, totals, $t, + fullScreenLoader) { 'use strict'; - return function (isApplied, isLoading) { + return function (isApplied) { var quoteId = quote.getQuoteId(), url = urlManager.getCancelCouponUrl(quoteId), message = $t('Your coupon was successfully removed.'); + messageContainer.clear(); + fullScreenLoader.startLoader(); return storage.delete( url, @@ -39,6 +43,7 @@ define( $.when(deferred).done(function () { isApplied(false); totals.isLoading(false); + fullScreenLoader.stopLoader(); }); messageContainer.addSuccessMessage({ 'message': message @@ -47,12 +52,9 @@ define( ).fail( function (response) { totals.isLoading(false); + fullScreenLoader.stopLoader(); errorProcessor.process(response, messageContainer); } - ).always( - function () { - isLoading(false); - } ); }; } diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js index 606fe4013ea76..2193dd7abbb89 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -18,25 +18,22 @@ define( 'mage/storage', 'mage/translate', 'Magento_Checkout/js/action/get-payment-information', - 'Magento_Checkout/js/model/totals' + 'Magento_Checkout/js/model/totals', + 'Magento_Checkout/js/model/full-screen-loader' ], function ( - ko, - $, - quote, - urlManager, - errorProcessor, - messageContainer, - storage, - $t, - getPaymentInformationAction, - totals + ko, $, quote, urlManager, errorProcessor, messageContainer, storage, $t, getPaymentInformationAction, totals, + fullScreenLoader ) { 'use strict'; - return function (couponCode, isApplied, isLoading) { - var quoteId = quote.getQuoteId(); - var url = urlManager.getApplyCouponUrl(couponCode, quoteId); - var message = $t('Your coupon was successfully applied.'); + + return function (couponCode, isApplied) { + var quoteId = quote.getQuoteId(), + url = urlManager.getApplyCouponUrl(couponCode, quoteId), + message = $t('Your coupon was successfully applied.'); + + fullScreenLoader.startLoader(); + return storage.put( url, {}, @@ -45,19 +42,22 @@ define( function (response) { if (response) { var deferred = $.Deferred(); - isLoading(false); + isApplied(true); totals.isLoading(true); getPaymentInformationAction(deferred); $.when(deferred).done(function () { + fullScreenLoader.stopLoader(); totals.isLoading(false); }); - messageContainer.addSuccessMessage({'message': message}); + messageContainer.addSuccessMessage({ + 'message': message + }); } } ).fail( function (response) { - isLoading(false); + fullScreenLoader.stopLoader(); totals.isLoading(false); errorProcessor.process(response, messageContainer); } diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/model/payment/discount-messages.js b/app/code/Magento/SalesRule/view/frontend/web/js/model/payment/discount-messages.js index a174626dd45f2..b3c89892f7258 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/model/payment/discount-messages.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/model/payment/discount-messages.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define( diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/cart/totals/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/cart/totals/discount.js index bf4e88d5ebfed..ddab853217862 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/view/cart/totals/discount.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/cart/totals/discount.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global define*/ diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount-messages.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount-messages.js index 277d80b583c4a..8fc2a4a17be94 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount-messages.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount-messages.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js index 8e8c0798ff3b5..1071a4aac343f 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define( @@ -13,49 +13,53 @@ define( ], function ($, ko, Component, quote, setCouponCodeAction, cancelCouponAction) { 'use strict'; - var totals = quote.getTotals(); - var couponCode = ko.observable(null); + + var totals = quote.getTotals(), + couponCode = ko.observable(null), + isApplied = ko.observable(couponCode() != null); + if (totals()) { couponCode(totals()['coupon_code']); } - var isApplied = ko.observable(couponCode() != null); - var isLoading = ko.observable(false); + return Component.extend({ defaults: { template: 'Magento_SalesRule/payment/discount' }, couponCode: couponCode, + /** * Applied flag */ isApplied: isApplied, - isLoading: isLoading, + /** * Coupon code application procedure */ apply: function() { if (this.validate()) { - isLoading(true); - setCouponCodeAction(couponCode(), isApplied, isLoading); + setCouponCodeAction(couponCode(), isApplied); } }, + /** * Cancel using coupon */ cancel: function() { if (this.validate()) { - isLoading(true); couponCode(''); - cancelCouponAction(isApplied, isLoading); + cancelCouponAction(isApplied); } }, + /** * Coupon form validation * - * @returns {boolean} + * @returns {Boolean} */ - validate: function() { + validate: function () { var form = '#discount-form'; + return $(form).validation() && $(form).validation('isValid'); } }); diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js index 1b7fe0bbef33c..37b90681e4741 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js +++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global define*/ diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html index 6b5d134ea5b24..1711ebb7e6670 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html +++ b/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html index d6bc4c764d571..c4b13d9bf3940 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html +++ b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html @@ -1,6 +1,6 @@ @@ -15,7 +15,7 @@ -
+
diff --git a/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml b/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml new file mode 100644 index 0000000000000..8e2938dff5b44 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml @@ -0,0 +1,21 @@ + + + + + + + + + Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox + Magento_ConfigurableProduct::product/price/final_price.phtml + + + + + + diff --git a/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/final_price.phtml b/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/final_price.phtml new file mode 100644 index 0000000000000..c1d561ede5d95 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/final_price.phtml @@ -0,0 +1,60 @@ + + +getPriceType('regular_price'); + +/** @var \Magento\Framework\Pricing\Price\PriceInterface $finalPriceModel */ +$finalPriceModel = $block->getPriceType('final_price'); +$idSuffix = $block->getIdSuffix() ? $block->getIdSuffix() : ''; +$schema = ($block->getZone() == 'item_view') ? true : false; +?> +isProductList() && $block->hasSpecialPrice()): ?> + + renderAmount($finalPriceModel->getAmount(), [ + 'display_label' => __('Special Price'), + 'price_id' => $block->getPriceId('product-price-' . $idSuffix), + 'price_type' => 'finalPrice', + 'include_container' => true, + 'schema' => $schema + ]); ?> + + + renderAmount($priceModel->getAmount(), [ + 'display_label' => __('Regular Price'), + 'price_id' => $block->getPriceId('old-price-' . $idSuffix), + 'price_type' => 'oldPrice', + 'include_container' => true, + 'skip_adjustments' => true + ]); ?> + + + renderAmount($finalPriceModel->getAmount(), [ + 'price_id' => $block->getPriceId('product-price-' . $idSuffix), + 'price_type' => 'finalPrice', + 'include_container' => true, + 'schema' => $schema + ]); ?> + + +showMinimalPrice()): ?> + getUseLinkForAsLowAs()):?> + + renderAmountMinimal(); ?> + + + + renderAmountMinimal(); ?> + + + diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml b/app/code/Magento/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml index d8f6ae86bd32a..302e246502433 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml +++ b/app/code/Magento/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_configure_type_configurable.xml b/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_configure_type_configurable.xml index bd61a5d5db520..84ee21b4b3c73 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_configure_type_configurable.xml +++ b/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_configure_type_configurable.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_item_renderers.xml b/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_item_renderers.xml index 9d22b2a65cc2e..9577f947a7a48 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_item_renderers.xml +++ b/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_cart_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml b/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml index 0993cbf80770f..e861caa27aa2d 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml +++ b/app/code/Magento/ConfigurableProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/requirejs-config.js b/app/code/Magento/ConfigurableProduct/view/frontend/requirejs-config.js index 8794db668f40b..58b294fe7face 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/requirejs-config.js +++ b/app/code/Magento/ConfigurableProduct/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,4 +9,4 @@ var config = { configurable: 'Magento_ConfigurableProduct/js/configurable' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/templates/js/components.phtml b/app/code/Magento/ConfigurableProduct/view/frontend/templates/js/components.phtml index e490a6aa04923..bdcb2e9bf7747 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/ConfigurableProduct/view/frontend/templates/js/components.phtml @@ -1,6 +1,6 @@ decorateArray($block->getAllowAttributes()); "#product_addtocart_form": { "configurable": { "spConfig": getJsonConfig() ?>, - "onlyMainImg": getVar('change_only_base_image', 'Magento_ConfigurableProduct') ?: 'false'; ?> + "gallerySwitchStrategy": "getVar('gallery_switch_strategy', + 'Magento_ConfigurableProduct') ?: 'replace'; ?>" } } } diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js index d38e2760f1dc7..0838d157a10aa 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ @@ -28,7 +28,17 @@ define([ '<% } %>', mediaGallerySelector: '[data-gallery-role=gallery-placeholder]', mediaGalleryInitial: null, - onlyMainImg: false + slyOldPriceSelector: '.sly-old-price', + + /** + * Defines the mechanism of how images of a gallery should be + * updated when user switches between configurations of a product. + * + * As for now value of this option can be either 'replace' or 'prepend'. + * + * @type {String} + */ + gallerySwitchStrategy: 'replace' }, /** @@ -53,6 +63,8 @@ define([ // Setup/configure values to inputs this._configureForValues(); + + $(this.element).trigger('configurable.initialized'); }, /** @@ -82,10 +94,10 @@ define([ this.inputSimpleProduct = this.element.find(options.selectSimpleProduct); - gallery.on('gallery:loaded', function () { - var galleryObject = gallery.data('gallery'); - options.mediaGalleryInitial = galleryObject.returnCurrentImages(); - }); + gallery.data('gallery') ? + this._onGalleryLoaded(gallery) : + gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery)); + }, /** @@ -246,6 +258,7 @@ define([ this._resetChildren(element); } this._reloadPrice(); + this._displayRegularPriceBlock(this.simpleProduct); this._changeProductImage(); }, @@ -255,46 +268,33 @@ define([ */ _changeProductImage: function () { var images, - initialImages = $.extend(true, [], this.options.mediaGalleryInitial), + initialImages = this.options.mediaGalleryInitial, galleryObject = $(this.options.mediaGallerySelector).data('gallery'); - if (this.options.spConfig.images[this.simpleProduct]) { - images = $.extend(true, [], this.options.spConfig.images[this.simpleProduct]); + if (!galleryObject) { + return; } - function updateGallery(imagesArr) { - var imgToUpdate, - mainImg; + images = this.options.spConfig.images[this.simpleProduct]; - mainImg = imagesArr.filter(function (img) { - return img.isMain; - }); + if (images) { + if (this.options.gallerySwitchStrategy === 'prepend') { + images = images.concat(initialImages); + } - imgToUpdate = mainImg.length ? mainImg[0] : imagesArr[0]; - galleryObject.updateDataByIndex(0, imgToUpdate); - galleryObject.seek(1); - } + images = $.extend(true, [], images); - if (galleryObject) { - if (images) { - images.map(function (img) { - img.type = 'image'; - }); + images.forEach(function (img) { + img.type = 'image'; + }); - if (this.options.onlyMainImg) { - updateGallery(images); - } else { - galleryObject.updateData(images) - } - } else { - if (this.options.onlyMainImg) { - updateGallery(initialImages); - } else { - galleryObject.updateData(this.options.mediaGalleryInitial); - $(this.options.mediaGallerySelector).AddFotoramaVideoEvents(); - } - } + galleryObject.updateData(images); + } else { + galleryObject.updateData(initialImages); + $(this.options.mediaGallerySelector).AddFotoramaVideoEvents(); } + + galleryObject.first(); }, /** @@ -442,7 +442,7 @@ define([ }, /** - * Returns pracies for configured products + * Returns prices for configured products * * @param {*} config - Products configuration * @returns {*} @@ -485,8 +485,35 @@ define([ undefined : _.first(config.allowedProducts); - } + }, + /** + * Show or hide regular price block + * + * @param {*} optionId + * @private + */ + _displayRegularPriceBlock: function (optionId) { + if (typeof optionId != 'undefined' + && this.options.spConfig.optionPrices[optionId].oldPrice.amount + != this.options.spConfig.optionPrices[optionId].finalPrice.amount + ) { + $(this.options.slyOldPriceSelector).show(); + } else { + $(this.options.slyOldPriceSelector).hide(); + } + }, + + /** + * Callback which fired after gallery gets initialized. + * + * @param {HTMLElement} element - DOM element associated with gallery. + */ + _onGalleryLoaded: function (element) { + var galleryObject = element.data('gallery'); + + this.options.mediaGalleryInitial = galleryObject.returnCurrentImages(); + } }); return $.mage.configurable; diff --git a/app/code/Magento/Contact/Block/ContactForm.php b/app/code/Magento/Contact/Block/ContactForm.php index 58480f8412f85..f2263ecabb955 100644 --- a/app/code/Magento/Contact/Block/ContactForm.php +++ b/app/code/Magento/Contact/Block/ContactForm.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Contact/etc/adminhtml/system.xml b/app/code/Magento/Contact/etc/adminhtml/system.xml index ca1ced83457d4..6d39846019a36 100644 --- a/app/code/Magento/Contact/etc/adminhtml/system.xml +++ b/app/code/Magento/Contact/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/etc/config.xml b/app/code/Magento/Contact/etc/config.xml index c40b752cf17c4..3a3e3460585b9 100644 --- a/app/code/Magento/Contact/etc/config.xml +++ b/app/code/Magento/Contact/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/etc/di.xml b/app/code/Magento/Contact/etc/di.xml new file mode 100644 index 0000000000000..0800e42b0ec0c --- /dev/null +++ b/app/code/Magento/Contact/etc/di.xml @@ -0,0 +1,16 @@ + + + + + + + 1 + + + + diff --git a/app/code/Magento/Contact/etc/email_templates.xml b/app/code/Magento/Contact/etc/email_templates.xml index 17bcfeb0d18a5..be2cf76d5911b 100644 --- a/app/code/Magento/Contact/etc/email_templates.xml +++ b/app/code/Magento/Contact/etc/email_templates.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/etc/frontend/di.xml b/app/code/Magento/Contact/etc/frontend/di.xml index d376dca8c834d..b520c9f0e865d 100644 --- a/app/code/Magento/Contact/etc/frontend/di.xml +++ b/app/code/Magento/Contact/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/etc/frontend/page_types.xml b/app/code/Magento/Contact/etc/frontend/page_types.xml index bdf9f108ba355..a6f630d892114 100644 --- a/app/code/Magento/Contact/etc/frontend/page_types.xml +++ b/app/code/Magento/Contact/etc/frontend/page_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/etc/frontend/routes.xml b/app/code/Magento/Contact/etc/frontend/routes.xml index ab07f5492bdbf..ba548c605b71b 100644 --- a/app/code/Magento/Contact/etc/frontend/routes.xml +++ b/app/code/Magento/Contact/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Contact/etc/module.xml b/app/code/Magento/Contact/etc/module.xml index 837b37efec72a..ea6c3d05c692c 100644 --- a/app/code/Magento/Contact/etc/module.xml +++ b/app/code/Magento/Contact/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/registration.php b/app/code/Magento/Contact/registration.php index b7e0223259d3b..6d3f8dc31a95d 100644 --- a/app/code/Magento/Contact/registration.php +++ b/app/code/Magento/Contact/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Contact/view/frontend/layout/contact_index_index.xml b/app/code/Magento/Contact/view/frontend/layout/contact_index_index.xml index ff22911fc0e75..740647609b195 100644 --- a/app/code/Magento/Contact/view/frontend/layout/contact_index_index.xml +++ b/app/code/Magento/Contact/view/frontend/layout/contact_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/view/frontend/layout/default.xml b/app/code/Magento/Contact/view/frontend/layout/default.xml index 6eb2f280e164d..a97cf0ddc64e0 100644 --- a/app/code/Magento/Contact/view/frontend/layout/default.xml +++ b/app/code/Magento/Contact/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Contact/view/frontend/templates/form.phtml b/app/code/Magento/Contact/view/frontend/templates/form.phtml index 63cf1929e38c2..2ed9adc8aed2f 100644 --- a/app/code/Magento/Contact/view/frontend/templates/form.phtml +++ b/app/code/Magento/Contact/view/frontend/templates/form.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Cookie/etc/config.xml b/app/code/Magento/Cookie/etc/config.xml index f50e5fea8facd..4266c755f7737 100644 --- a/app/code/Magento/Cookie/etc/config.xml +++ b/app/code/Magento/Cookie/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cookie/etc/di.xml b/app/code/Magento/Cookie/etc/di.xml index 0cd62d0632f37..73e5dacb9b2fe 100644 --- a/app/code/Magento/Cookie/etc/di.xml +++ b/app/code/Magento/Cookie/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cookie/etc/frontend/routes.xml b/app/code/Magento/Cookie/etc/frontend/routes.xml index 70ea487ab5b16..ca903f9d58e5b 100644 --- a/app/code/Magento/Cookie/etc/frontend/routes.xml +++ b/app/code/Magento/Cookie/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Cookie/etc/module.xml b/app/code/Magento/Cookie/etc/module.xml index 0efe82649693a..75b6e7bad6df0 100644 --- a/app/code/Magento/Cookie/etc/module.xml +++ b/app/code/Magento/Cookie/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cookie/registration.php b/app/code/Magento/Cookie/registration.php index ab3fb6ac73e3f..696427c020dc3 100644 --- a/app/code/Magento/Cookie/registration.php +++ b/app/code/Magento/Cookie/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Cookie/view/frontend/requirejs-config.js b/app/code/Magento/Cookie/view/frontend/requirejs-config.js index 7c90d480ebdfc..680ca42ebd11d 100644 --- a/app/code/Magento/Cookie/view/frontend/requirejs-config.js +++ b/app/code/Magento/Cookie/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -10,4 +10,4 @@ var config = { cookieNotices: 'Magento_Cookie/js/notices' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml b/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml index 0ef6e395c03c5..e5e4438301902 100644 --- a/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml +++ b/app/code/Magento/Cookie/view/frontend/templates/html/notices.phtml @@ -1,6 +1,6 @@ @@ -11,4 +11,4 @@ "requireCookie": getScriptOptions(); ?> } } - \ No newline at end of file + diff --git a/app/code/Magento/Cookie/view/frontend/web/js/notices.js b/app/code/Magento/Cookie/view/frontend/web/js/notices.js index 8d0e81c473874..d7f0fa3874756 100644 --- a/app/code/Magento/Cookie/view/frontend/web/js/notices.js +++ b/app/code/Magento/Cookie/view/frontend/web/js/notices.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ diff --git a/app/code/Magento/Cookie/view/frontend/web/js/require-cookie.js b/app/code/Magento/Cookie/view/frontend/web/js/require-cookie.js index 8dfa50ac26d8c..ca8861cc68533 100644 --- a/app/code/Magento/Cookie/view/frontend/web/js/require-cookie.js +++ b/app/code/Magento/Cookie/view/frontend/web/js/require-cookie.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint evil:true browser:true jquery:true */ diff --git a/app/code/Magento/Cron/Console/Command/CronCommand.php b/app/code/Magento/Cron/Console/Command/CronCommand.php index 9c541db244fad..46b87e536187d 100644 --- a/app/code/Magento/Cron/Console/Command/CronCommand.php +++ b/app/code/Magento/Cron/Console/Command/CronCommand.php @@ -1,6 +1,6 @@ _defaultReader = $this->getMockBuilder( - 'Magento\Store\Model\Config\Reader\DefaultReader' - )->disableOriginalConstructor()->getMock(); + \Magento\Framework\App\Config\Scope\ReaderInterface::class + )->getMockForAbstractClass(); $this->_converter = new \Magento\Cron\Model\Config\Converter\Db(); $this->_reader = new \Magento\Cron\Model\Config\Reader\Db($this->_defaultReader, $this->_converter); } diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/XmlTest.php b/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/XmlTest.php index 30c56734d1ad3..e1383cf3ca1be 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/XmlTest.php +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/XmlTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_duplicates.xml b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_duplicates.xml index b899a6ee89dee..1512aafb9abb2 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_duplicates.xml +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_duplicates.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_node_typo.xml b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_node_typo.xml index a5cd3f2b4413d..17e6850474e79 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_node_typo.xml +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_node_typo.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_instance.xml b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_instance.xml index 5243210c7c736..1b7f2a2f70daf 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_instance.xml +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_instance.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_method.xml b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_method.xml index 35ce23871fcf9..1c0654811d4cd 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_method.xml +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_method.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_name.xml b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_name.xml index 747bf5febb209..8bf7f63b97979 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_name.xml +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_invalid_without_name.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid.xml b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid.xml index 444c228299dfe..79c4da8a7837e 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid.xml +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid_without_schedule.xml b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid_without_schedule.xml index e527465d1fe3e..4e255306e503c 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid_without_schedule.xml +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/_files/crontab_valid_without_schedule.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Cron/Test/Unit/Model/ConfigTest.php index 2f57bc51ec140..51787e30e86ef 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Cron/Test/Unit/Model/ConfigTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Cron/etc/cron_groups.xml b/app/code/Magento/Cron/etc/cron_groups.xml index 339ed3fa4a734..d3e091c862531 100644 --- a/app/code/Magento/Cron/etc/cron_groups.xml +++ b/app/code/Magento/Cron/etc/cron_groups.xml @@ -1,7 +1,7 @@ @@ -15,4 +15,4 @@ 600 0 - \ No newline at end of file + diff --git a/app/code/Magento/Cron/etc/cron_groups.xsd b/app/code/Magento/Cron/etc/cron_groups.xsd index 87d2cb5bfb13e..15074997589de 100644 --- a/app/code/Magento/Cron/etc/cron_groups.xsd +++ b/app/code/Magento/Cron/etc/cron_groups.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/etc/crontab.xsd b/app/code/Magento/Cron/etc/crontab.xsd index 2a2ae3ff06a00..68279da5aec84 100644 --- a/app/code/Magento/Cron/etc/crontab.xsd +++ b/app/code/Magento/Cron/etc/crontab.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/etc/crontab/events.xml b/app/code/Magento/Cron/etc/crontab/events.xml index b24feb04c577f..9de72ebb03eb5 100644 --- a/app/code/Magento/Cron/etc/crontab/events.xml +++ b/app/code/Magento/Cron/etc/crontab/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/etc/di.xml b/app/code/Magento/Cron/etc/di.xml index 740eff2aed432..0f7897c58b8fe 100644 --- a/app/code/Magento/Cron/etc/di.xml +++ b/app/code/Magento/Cron/etc/di.xml @@ -1,7 +1,7 @@ @@ -10,7 +10,7 @@ - Magento\Store\Model\Config\Reader\DefaultReader + DefaultScopeReader diff --git a/app/code/Magento/Cron/etc/module.xml b/app/code/Magento/Cron/etc/module.xml index 6d197d16b78a8..288aa6fbec23e 100644 --- a/app/code/Magento/Cron/etc/module.xml +++ b/app/code/Magento/Cron/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Cron/registration.php b/app/code/Magento/Cron/registration.php index 2510e93c6b76b..227c716af1862 100644 --- a/app/code/Magento/Cron/registration.php +++ b/app/code/Magento/Cron/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/CurrencySymbol/etc/adminhtml/menu.xml b/app/code/Magento/CurrencySymbol/etc/adminhtml/menu.xml index ae6e8ef40de84..5dbf49d2c1cf3 100644 --- a/app/code/Magento/CurrencySymbol/etc/adminhtml/menu.xml +++ b/app/code/Magento/CurrencySymbol/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CurrencySymbol/etc/adminhtml/routes.xml b/app/code/Magento/CurrencySymbol/etc/adminhtml/routes.xml index bf0c1873e0f2d..31353a45c2859 100644 --- a/app/code/Magento/CurrencySymbol/etc/adminhtml/routes.xml +++ b/app/code/Magento/CurrencySymbol/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CurrencySymbol/etc/di.xml b/app/code/Magento/CurrencySymbol/etc/di.xml index 15de35ba58ad2..cbce50306bc45 100644 --- a/app/code/Magento/CurrencySymbol/etc/di.xml +++ b/app/code/Magento/CurrencySymbol/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CurrencySymbol/etc/events.xml b/app/code/Magento/CurrencySymbol/etc/events.xml index 7f5e98b1dcd60..aff0fea744c43 100644 --- a/app/code/Magento/CurrencySymbol/etc/events.xml +++ b/app/code/Magento/CurrencySymbol/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CurrencySymbol/etc/module.xml b/app/code/Magento/CurrencySymbol/etc/module.xml index 96994b03ce6c7..cbda20acdad82 100644 --- a/app/code/Magento/CurrencySymbol/etc/module.xml +++ b/app/code/Magento/CurrencySymbol/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CurrencySymbol/registration.php b/app/code/Magento/CurrencySymbol/registration.php index 15ba3ffc36701..ab086a95e2d6c 100644 --- a/app/code/Magento/CurrencySymbol/registration.php +++ b/app/code/Magento/CurrencySymbol/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/layout/adminhtml_system_currencysymbol_index.xml b/app/code/Magento/CurrencySymbol/view/adminhtml/layout/adminhtml_system_currencysymbol_index.xml index 7fc5203224c05..bf7126f432cf9 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/layout/adminhtml_system_currencysymbol_index.xml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/layout/adminhtml_system_currencysymbol_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index b10225a13ee18..2de297bbc7eb8 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -1,6 +1,6 @@ getChildHtml('import_services') ?>
- \ No newline at end of file + diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/system/currency/rates.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/system/currency/rates.phtml index 20e36a1d0ce80..e6b0635b2e292 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/system/currency/rates.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/system/currency/rates.phtml @@ -1,6 +1,6 @@ authentication instanceof AuthenticationInterface)) { - return \Magento\Framework\App\ObjectManager::getInstance()->get( + return ObjectManager::getInstance()->get( \Magento\Customer\Model\AuthenticationInterface::class ); } else { @@ -118,7 +125,7 @@ private function getAuthentication() private function getEmailNotification() { if (!($this->emailNotification instanceof EmailNotificationInterface)) { - return \Magento\Framework\App\ObjectManager::getInstance()->get( + return ObjectManager::getInstance()->get( EmailNotificationInterface::class ); } else { @@ -196,7 +203,7 @@ public function execute() private function getScopeConfig() { if (!($this->scopeConfig instanceof \Magento\Framework\App\Config\ScopeConfigInterface)) { - return \Magento\Framework\App\ObjectManager::getInstance()->get( + return ObjectManager::getInstance()->get( \Magento\Framework\App\Config\ScopeConfigInterface::class ); } else { @@ -241,7 +248,12 @@ private function populateNewCustomerDataObject( \Magento\Framework\App\RequestInterface $inputData, \Magento\Customer\Api\Data\CustomerInterface $currentCustomerData ) { - $customerDto = $this->customerExtractor->extract(self::FORM_DATA_EXTRACTOR_CODE, $inputData); + $attributeValues = $this->getCustomerMapper()->toFlatArray($currentCustomerData); + $customerDto = $this->customerExtractor->extract( + self::FORM_DATA_EXTRACTOR_CODE, + $inputData, + $attributeValues + ); $customerDto->setId($currentCustomerData->getId()); if (!$customerDto->getAddresses()) { $customerDto->setAddresses($currentCustomerData->getAddresses()); @@ -299,4 +311,19 @@ private function processChangeEmailRequest(\Magento\Customer\Api\Data\CustomerIn } } } + + /** + * Get Customer Mapper instance + * + * @return Mapper + * + * @deprecated + */ + private function getCustomerMapper() + { + if ($this->customerMapper === null) { + $this->customerMapper = ObjectManager::getInstance()->get('Magento\Customer\Model\Customer\Mapper'); + } + return $this->customerMapper; + } } diff --git a/app/code/Magento/Customer/Controller/Account/ForgotPassword.php b/app/code/Magento/Customer/Controller/Account/ForgotPassword.php index 7cb5a4ce7fa01..0c7cae6e1ae1d 100644 --- a/app/code/Magento/Customer/Controller/Account/ForgotPassword.php +++ b/app/code/Magento/Customer/Controller/Account/ForgotPassword.php @@ -1,7 +1,7 @@ messageManager->addError($message); $this->session->setUsername($login['username']); + } catch (LocalizedException $e) { + $message = $e->getMessage(); + $this->messageManager->addError($message); + $this->session->setUsername($login['username']); } catch (\Exception $e) { // PA DSS violation: throwing or logging an exception here can disclose customer password $this->messageManager->addError( diff --git a/app/code/Magento/Customer/Controller/Account/Logout.php b/app/code/Magento/Customer/Controller/Account/Logout.php index 1f0dd1057e73d..0c182b0da4fe3 100644 --- a/app/code/Magento/Customer/Controller/Account/Logout.php +++ b/app/code/Magento/Customer/Controller/Account/Logout.php @@ -1,7 +1,7 @@ getCustomerId() !== $this->_getSession()->getCustomerId()) { throw new \Exception(); } - $existingAddressData = $this->_dataProcessor->buildOutputDataArray( - $existingAddress, - '\Magento\Customer\Api\Data\AddressInterface' - ); - $existingAddressData['region_code'] = $existingAddress->getRegion()->getRegionCode(); - $existingAddressData['region'] = $existingAddress->getRegion()->getRegion(); + $existingAddressData = $this->getCustomerAddressMapper()->toFlatArray($existingAddress); } return $existingAddressData; } @@ -212,4 +214,19 @@ public function execute() return $this->resultRedirectFactory->create()->setUrl($this->_redirect->error($url)); } + + /** + * Get Customer Address Mapper instance + * + * @return Mapper + * + * @deprecated + */ + private function getCustomerAddressMapper() + { + if ($this->customerAddressMapper === null) { + $this->customerAddressMapper = ObjectManager::getInstance()->get('Magento\Customer\Model\Address\Mapper'); + } + return $this->customerAddressMapper; + } } diff --git a/app/code/Magento/Customer/Controller/Address/Index.php b/app/code/Magento/Customer/Controller/Address/Index.php index 31c991b1a47b4..711f7b1753d86 100644 --- a/app/code/Magento/Customer/Controller/Address/Index.php +++ b/app/code/Magento/Customer/Controller/Address/Index.php @@ -1,7 +1,7 @@ fileUploaderFactory = $fileUploaderFactory; + $this->addressMetadataService = $addressMetadataService; + $this->logger = $logger; + parent::__construct($context); + } + + /** + * @inheritDoc + */ + public function execute() + { + try { + if (empty($_FILES)) { + throw new \Exception('$_FILES array is empty.'); + } + + // Must be executed before any operations with $_FILES! + $this->convertFilesArray(); + + $attributeCode = key($_FILES['address']['name']); + $attributeMetadata = $this->addressMetadataService->getAttributeMetadata($attributeCode); + + /** @var FileUploader $fileUploader */ + $fileUploader = $this->fileUploaderFactory->create([ + 'attributeMetadata' => $attributeMetadata, + 'entityTypeCode' => AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + 'scope' => 'address', + ]); + + $errors = $fileUploader->validate(); + if (true !== $errors) { + $errorMessage = implode('
', $errors); + throw new LocalizedException(__($errorMessage)); + } + + $result = $fileUploader->upload(); + } catch (LocalizedException $e) { + $result = [ + 'error' => $e->getMessage(), + 'errorcode' => $e->getCode(), + ]; + } catch (\Exception $e) { + $this->logger->critical($e); + $result = [ + 'error' => __('Something went wrong while saving file.'), + 'errorcode' => $e->getCode(), + ]; + } + + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($result); + return $resultJson; + } + + /** + * Update global $_FILES array. Convert data to standard form + * + * NOTE: This conversion is required to use \Magento\Framework\File\Uploader::_setUploadFileId($fileId) method. + * + * @return void + */ + private function convertFilesArray() + { + foreach ($_FILES['address'] as $itemKey => $item) { + foreach ($item as $value) { + if (is_array($value)) { + $_FILES['address'][$itemKey] = [ + key($value) => current($value), + ]; + } + } + } + } +} diff --git a/app/code/Magento/Customer/Controller/Adminhtml/File/Customer/Upload.php b/app/code/Magento/Customer/Controller/Adminhtml/File/Customer/Upload.php new file mode 100644 index 0000000000000..5a73cb3cec621 --- /dev/null +++ b/app/code/Magento/Customer/Controller/Adminhtml/File/Customer/Upload.php @@ -0,0 +1,104 @@ +fileUploaderFactory = $fileUploaderFactory; + $this->customerMetadataService = $customerMetadataService; + $this->logger = $logger; + parent::__construct($context); + } + + /** + * @inheritDoc + */ + public function execute() + { + try { + if (empty($_FILES)) { + throw new \Exception('$_FILES array is empty.'); + } + + $attributeCode = key($_FILES['customer']['name']); + $attributeMetadata = $this->customerMetadataService->getAttributeMetadata($attributeCode); + + /** @var FileUploader $fileUploader */ + $fileUploader = $this->fileUploaderFactory->create([ + 'attributeMetadata' => $attributeMetadata, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'scope' => 'customer', + ]); + + $errors = $fileUploader->validate(); + if (true !== $errors) { + $errorMessage = implode('
', $errors); + throw new LocalizedException(__($errorMessage)); + } + + $result = $fileUploader->upload(); + } catch (LocalizedException $e) { + $result = [ + 'error' => $e->getMessage(), + 'errorcode' => $e->getCode(), + ]; + } catch (\Exception $e) { + $this->logger->critical($e); + $result = [ + 'error' => __('Something went wrong while saving file.'), + 'errorcode' => $e->getCode(), + ]; + } + + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $resultJson->setData($result); + return $resultJson; + } +} diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Group.php b/app/code/Magento/Customer/Controller/Adminhtml/Group.php index 629a381910627..6387de1811958 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Group.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Group.php @@ -1,6 +1,6 @@ getMessage(); } $this->_addSessionErrorMessages($messages); + } catch (SecurityViolationException $exception) { + $this->messageManager->addErrorMessage($exception->getMessage()); } catch (\Exception $exception) { $this->messageManager->addException( $exception, diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php index 26006bfa8dfc8..0a90ee4bd44ab 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php @@ -1,21 +1,17 @@ getRequest()->getPost('customer')) { - $serviceAttributes = [ + $additionalAttributes = [ CustomerInterface::DEFAULT_BILLING, CustomerInterface::DEFAULT_SHIPPING, 'confirmation', 'sendemail_store_id', + 'extension_attributes', ]; $customerData = $this->_extractData( $this->getRequest(), 'adminhtml_customer', - \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, - $serviceAttributes, + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + $additionalAttributes, 'customer' ); } @@ -72,6 +69,7 @@ protected function _extractCustomerData() * @param string $scope scope of the request * @param \Magento\Customer\Model\Metadata\Form $metadataForm to use for extraction * @return array Filtered customer data + * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _extractData( \Magento\Framework\App\RequestInterface $request, @@ -81,34 +79,35 @@ protected function _extractData( $scope = null, \Magento\Customer\Model\Metadata\Form $metadataForm = null ) { - if ($metadataForm === null) { - $metadataForm = $this->_formFactory->create( - $entityType, - $formCode, - [], - false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE - ); - } - $filteredData = $metadataForm->extractData($request, $scope); + $metadataForm = $metadataForm ? $metadataForm : $this->getMetadataForm($entityType, $formCode, $scope); + $formData = $metadataForm->extractData($request, $scope); + $formData = $metadataForm->compactData($formData); + // Initialize additional attributes + /** @var \Magento\Framework\DataObject $object */ $object = $this->_objectFactory->create(['data' => $request->getPostValue()]); $requestData = $object->getData($scope); foreach ($additionalAttributes as $attributeCode) { - $filteredData[$attributeCode] = isset($requestData[$attributeCode]) ? $requestData[$attributeCode] : false; + $formData[$attributeCode] = isset($requestData[$attributeCode]) ? $requestData[$attributeCode] : false; } + // Unset unused attributes $formAttributes = $metadataForm->getAttributes(); - /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute */ foreach ($formAttributes as $attribute) { + /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute */ $attributeCode = $attribute->getAttributeCode(); - $frontendInput = $attribute->getFrontendInput(); - if ($frontendInput != 'boolean' && $filteredData[$attributeCode] === false) { - unset($filteredData[$attributeCode]); + if ($attribute->getFrontendInput() != 'boolean' + && $formData[$attributeCode] === false + ) { + unset($formData[$attributeCode]); } } - return $filteredData; + if (empty($formData['extension_attributes'])) { + unset($formData['extension_attributes']); + } + + return $formData; } /** @@ -128,7 +127,7 @@ protected function saveDefaultFlags(array $addressIdList, array & $extractedCust $addressData = $this->_extractData( $this->getRequest(), 'adminhtml_customer_address', - \Magento\Customer\Api\AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + AddressMetadataInterface::ENTITY_TYPE_ADDRESS, ['default_billing', 'default_shipping'], $scope ); @@ -188,18 +187,16 @@ public function execute() { $returnToEdit = false; $originalRequestData = $this->getRequest()->getPostValue(); - $customerId = isset($originalRequestData['customer']['entity_id']) - ? $originalRequestData['customer']['entity_id'] - : null; + + $customerId = $this->getCurrentCustomerId(); + if ($originalRequestData) { try { // optional fields might be set in request for future processing by observers in other modules $customerData = $this->_extractCustomerData(); $addressesData = $this->_extractCustomerAddressData($customerData); - $request = $this->getRequest(); - $isExistingCustomer = (bool)$customerId; - $customer = $this->customerDataFactory->create(); - if ($isExistingCustomer) { + + if ($customerId) { $currentCustomer = $this->_customerRepository->getById($customerId); $customerData = array_merge( $this->customerMapper->toFlatArray($currentCustomer), @@ -208,6 +205,8 @@ public function execute() $customerData['id'] = $customerId; } + /** @var CustomerInterface $customer */ + $customer = $this->customerDataFactory->create(); $this->dataObjectHelper->populateWithArray( $customer, $customerData, @@ -232,17 +231,18 @@ public function execute() $this->_eventManager->dispatch( 'adminhtml_customer_prepare_save', - ['customer' => $customer, 'request' => $request] + ['customer' => $customer, 'request' => $this->getRequest()] ); $customer->setAddresses($addresses); - $customer->setStoreId($customerData['sendemail_store_id']); + if (isset($customerData['sendemail_store_id'])) { + $customer->setStoreId($customerData['sendemail_store_id']); + } // Save customer - if ($isExistingCustomer) { + if ($customerId) { $this->_customerRepository->save($customer); $this->getEmailNotification()->credentialsChanged($customer, $currentCustomer->getEmail()); - } else { $customer = $this->customerAccountManagement->createAccount($customer); $customerId = $customer->getId(); @@ -263,7 +263,7 @@ public function execute() // After save $this->_eventManager->dispatch( 'adminhtml_customer_save_after', - ['customer' => $customer, 'request' => $request] + ['customer' => $customer, 'request' => $this->getRequest()] ); $this->_getSession()->unsCustomerFormData(); // Done Saving customer, finish save action @@ -323,4 +323,59 @@ private function getEmailNotification() return $this->emailNotification; } } + + /** + * Get metadata form + * + * @param string $entityType + * @param string $formCode + * @param string $scope + * @return Form + */ + private function getMetadataForm($entityType, $formCode, $scope) + { + $attributeValues = []; + + if ($entityType == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { + $customerId = $this->getCurrentCustomerId(); + if ($customerId) { + $customer = $this->_customerRepository->getById($customerId); + $attributeValues = $this->customerMapper->toFlatArray($customer); + } + } + + if ($entityType == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) { + $scopeData = explode('/', $scope); + if (isset($scopeData[1]) && is_numeric($scopeData[1])) { + $customerAddress = $this->addressRepository->getById($scopeData[1]); + $attributeValues = $this->addressMapper->toFlatArray($customerAddress); + } + } + + $metadataForm = $this->_formFactory->create( + $entityType, + $formCode, + $attributeValues, + false, + Form::DONT_IGNORE_INVISIBLE + ); + + return $metadataForm; + } + + /** + * Retrieve current customer ID + * + * @return int + */ + private function getCurrentCustomerId() + { + $originalRequestData = $this->getRequest()->getPostValue(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + + $customerId = isset($originalRequestData['entity_id']) + ? $originalRequestData['entity_id'] + : null; + + return $customerId; + } } diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php index 7c1f23881ec3d..64d0f6e142c73 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php @@ -1,6 +1,6 @@ _formFactory->create( 'customer', 'adminhtml_customer', - $this->_extensibleDataObjectConverter->toFlatArray( - $customer, - [], - '\Magento\Customer\Api\Data\CustomerInterface' - ), + [], true ); $customerForm->setInvisibleIgnored(true); diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/ViewCart.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/ViewCart.php index c880905e5128e..8107a7cb74c42 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/ViewCart.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/ViewCart.php @@ -1,6 +1,6 @@ _objectManager->get('Magento\Framework\Filesystem'); $directory = $filesystem->getDirectoryRead(DirectoryList::MEDIA); - $fileName = 'customer' . '/' . ltrim($file, '/'); + $fileName = CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . ltrim($file, '/'); $path = $directory->getAbsolutePath($fileName); if (!$directory->isFile($fileName) && !$this->_objectManager->get('Magento\MediaStorage\Helper\File\Storage')->processStorageFile($path) @@ -175,7 +176,7 @@ public function execute() $contentType = 'application/octet-stream'; break; } - $stat = $directory->stat($path); + $stat = $directory->stat($fileName); $contentLength = $stat['size']; $contentModify = $stat['mtime']; diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php index c4a4f7b53baf6..fee33bfcd5e45 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php @@ -1,6 +1,6 @@ true, 'message' => $e->getMessage() ]; + } catch (LocalizedException $e) { + $response = [ + 'errors' => true, + 'message' => $e->getMessage() + ]; } catch (\Exception $e) { $response = [ 'errors' => true, diff --git a/app/code/Magento/Customer/Controller/Ajax/Logout.php b/app/code/Magento/Customer/Controller/Ajax/Logout.php index ba4da3dc10463..2700f239afaea 100644 --- a/app/code/Magento/Customer/Controller/Ajax/Logout.php +++ b/app/code/Magento/Customer/Controller/Ajax/Logout.php @@ -1,7 +1,7 @@ getRequest()->getParam('update_section_id'); - if ('false' == $updateSectionId) { + if ('false' === $updateSectionId) { $updateSectionId = false; } $response = $this->sectionPool->getSectionsData($sectionNames, (bool)$updateSectionId); @@ -70,9 +76,21 @@ public function execute() \Zend\Http\AbstractMessage::VERSION_11, 'Bad Request' ); - $response = ['message' => $e->getMessage()]; + $response = ['message' => $this->getEscaper()->escapeHtml($e->getMessage())]; } return $resultJson->setData($response); } + + /** + * @deprecated + * @return Escaper + */ + private function getEscaper() + { + if ($this->escaper == null) { + $this->escaper = $this->_objectManager->get(Escaper::class); + } + return $this->escaper; + } } diff --git a/app/code/Magento/Customer/CustomerData/Customer.php b/app/code/Magento/Customer/CustomerData/Customer.php index 6b7d0e15f7622..7a8b982ecdc6d 100644 --- a/app/code/Magento/Customer/CustomerData/Customer.php +++ b/app/code/Magento/Customer/CustomerData/Customer.php @@ -1,6 +1,6 @@ setFailuresNum($failuresNum); - $this->customerRepository->save($this->customerRepository->getById($customerId)); + $this->getCustomerAuthUpdate()->saveAuth($customerId); } /** @@ -117,7 +128,7 @@ public function unlock($customerId) $customerSecure->setFailuresNum(0); $customerSecure->setFirstFailure(null); $customerSecure->setLockExpires(null); - $this->customerRepository->save($this->customerRepository->getById($customerId)); + $this->getCustomerAuthUpdate()->saveAuth($customerId); } /** @@ -165,4 +176,19 @@ public function authenticate($customerId, $password) } return true; } + + /** + * Get customer authentication update model + * + * @return \Magento\Customer\Model\CustomerAuthUpdate + * @deprecated + */ + private function getCustomerAuthUpdate() + { + if ($this->customerAuthUpdate === null) { + $this->customerAuthUpdate = + \Magento\Framework\App\ObjectManager::getInstance()->get(CustomerAuthUpdate::class); + } + return $this->customerAuthUpdate; + } } diff --git a/app/code/Magento/Customer/Model/AuthenticationInterface.php b/app/code/Magento/Customer/Model/AuthenticationInterface.php index ee1264186d0d5..3e056c8e48909 100644 --- a/app/code/Magento/Customer/Model/AuthenticationInterface.php +++ b/app/code/Magento/Customer/Model/AuthenticationInterface.php @@ -1,6 +1,6 @@ session === null) { - $this->session = ObjectManager::getInstance()->get('Magento\Framework\Session\SessionManagerInterface'); + $this->session = ObjectManager::getInstance()->get( + \Magento\Framework\Session\SessionManagerInterface::class + ); } return $this->session; } @@ -145,6 +197,13 @@ public function getData() /** @var Customer $customer */ foreach ($items as $customer) { $result['customer'] = $customer->getData(); + + $this->overrideFileUploaderData($customer, $result['customer']); + + $result['customer'] = array_diff_key( + $result['customer'], + array_flip($this->forbiddenCustomerFields) + ); unset($result['address']); /** @var Address $address */ @@ -153,6 +212,8 @@ public function getData() $address->load($addressId); $result['address'][$addressId] = $address->getData(); $this->prepareAddressData($addressId, $result['address'], $result['customer']); + + $this->overrideFileUploaderData($address, $result['address'][$addressId]); } $this->loadedData[$customer->getId()] = $result; } @@ -167,6 +228,80 @@ public function getData() return $this->loadedData; } + /** + * Override file uploader UI component data + * + * Overrides data for attributes with frontend_input equal to 'image' or 'file'. + * + * @param Customer|Address $entity + * @param array $entityData + * @return void + */ + private function overrideFileUploaderData($entity, array &$entityData) + { + $attributes = $entity->getAttributes(); + foreach ($attributes as $attribute) { + /** @var Attribute $attribute */ + if (in_array($attribute->getFrontendInput(), $this->fileUploaderTypes)) { + $entityData[$attribute->getAttributeCode()] = $this->getFileUploaderData( + $entity->getEntityType(), + $attribute, + $entityData + ); + } + } + } + + /** + * Retrieve array of values required by file uploader UI component + * + * @param Type $entityType + * @param Attribute $attribute + * @param array $customerData + * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function getFileUploaderData( + Type $entityType, + Attribute $attribute, + array $customerData + ) { + $attributeCode = $attribute->getAttributeCode(); + + $file = isset($customerData[$attributeCode]) + ? $customerData[$attributeCode] + : ''; + + /** @var FileProcessor $fileProcessor */ + $fileProcessor = $this->getFileProcessorFactory()->create([ + 'entityTypeCode' => $entityType->getEntityTypeCode(), + ]); + + if (!empty($file) + && $fileProcessor->isExist($file) + ) { + $stat = $fileProcessor->getStat($file); + $viewUrl = $fileProcessor->getViewUrl($file, $attribute->getFrontendInput()); + } + + $fileName = $file; + if (strrpos($fileName, '/') !== false) { + $fileName = substr($fileName, strrpos($fileName, '/') + 1); + } + + if (!empty($file)) { + return [ + [ + 'file' => $file, + 'size' => isset($stat) ? $stat['size'] : 0, + 'url' => isset($viewUrl) ? $viewUrl : '', + 'name' => $fileName, + ], + ]; + } + return []; + } + /** * Get attributes meta * @@ -178,7 +313,7 @@ protected function getAttributesMeta(Type $entityType) { $meta = []; $attributes = $entityType->getAttributeCollection(); - /* @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */ + /* @var AbstractAttribute $attribute */ foreach ($attributes as $attribute) { $this->processFrontendInput($attribute, $meta); @@ -195,7 +330,12 @@ protected function getAttributesMeta(Type $entityType) } if ($attribute->usesSource()) { - $meta[$code]['arguments']['data']['config']['options'] = $attribute->getSource()->getAllOptions(); + if ($code == AddressInterface::COUNTRY_ID) { + $meta[$code]['arguments']['data']['config']['options'] = $this->getCountryByWebsiteSource() + ->getAllOptions(); + } else { + $meta[$code]['arguments']['data']['config']['options'] = $attribute->getSource()->getAllOptions(); + } } $rules = $this->eavValidationRules->build($attribute, $meta[$code]['arguments']['data']['config']); @@ -203,16 +343,160 @@ protected function getAttributesMeta(Type $entityType) $meta[$code]['arguments']['data']['config']['validation'] = $rules; } $meta[$code]['arguments']['data']['config']['componentType'] = Field::NAME; + + $this->overrideFileUploaderMetadata($entityType, $attribute, $meta[$code]['arguments']['data']['config']); } + + $this->processWebsiteMeta($meta); return $meta; } + /** + * Override file uploader UI component metadata + * + * Overrides metadata for attributes with frontend_input equal to 'image' or 'file'. + * + * @param Type $entityType + * @param AbstractAttribute $attribute + * @param array $config + * @return void + */ + private function overrideFileUploaderMetadata( + Type $entityType, + AbstractAttribute $attribute, + array &$config + ) { + if (in_array($attribute->getFrontendInput(), $this->fileUploaderTypes)) { + $maxFileSize = self::MAX_FILE_SIZE; + + if (isset($config['validation']['max_file_size'])) { + $maxFileSize = (int)$config['validation']['max_file_size']; + } + + $allowedExtensions = []; + + if (isset($config['validation']['file_extensions'])) { + $allowedExtensions = explode(',', $config['validation']['file_extensions']); + array_walk( + $allowedExtensions, + function (&$value) { + $value = strtolower(trim($value)); + } + ); + } + + $allowedExtensions = implode(' ', $allowedExtensions); + + $entityTypeCode = $entityType->getEntityTypeCode(); + $url = $this->getFileUploadUrl($entityTypeCode); + + $config = [ + 'formElement' => 'fileUploader', + 'componentType' => 'fileUploader', + 'maxFileSize' => $maxFileSize, + 'allowedExtensions' => $allowedExtensions, + 'uploaderConfig' => [ + 'url' => $url, + ], + 'label' => $this->getMetadataValue($config, 'label'), + 'sortOrder' => $this->getMetadataValue($config, 'sortOrder'), + 'required' => $this->getMetadataValue($config, 'required'), + 'visible' => $this->getMetadataValue($config, 'visible'), + 'validation' => $this->getMetadataValue($config, 'validation'), + ]; + } + } + + /** + * Retrieve metadata value + * + * @param array $config + * @param string $name + * @param mixed $default + * @return mixed + */ + private function getMetadataValue($config, $name, $default = null) + { + $value = isset($config[$name]) ? $config[$name] : $default; + return $value; + } + + /** + * Retrieve URL to file upload + * + * @param string $entityTypeCode + * @return string + */ + private function getFileUploadUrl($entityTypeCode) + { + switch ($entityTypeCode) { + case CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER: + $url = 'customer/file/customer_upload'; + break; + + case AddressMetadataInterface::ENTITY_TYPE_ADDRESS: + $url = 'customer/file/address_upload'; + break; + + default: + $url = ''; + break; + } + return $url; + } + + /** + * Retrieve Country With Website options Source + * @deprecated + * @return CountryWithWebsites + */ + private function getCountryByWebsiteSource() + { + if (!$this->countryByWebsiteSource) { + $this->countryByWebsiteSource = ObjectManager::getInstance()->get(CountryWithWebsites::class); + } + + return $this->countryByWebsiteSource; + } + + /** + * Retrieve Customer Share Config + * @deprecated + * @return \Magento\Customer\Model\Config\Share + */ + private function getShareConfig() + { + if (!$this->shareConfig) { + $this->shareConfig = ObjectManager::getInstance()->get(\Magento\Customer\Model\Config\Share::class); + } + + return $this->shareConfig; + } + + /** + * @param array $meta + * @return void + */ + private function processWebsiteMeta(&$meta) + { + if (isset($meta[CustomerInterface::WEBSITE_ID]) && $this->getShareConfig()->isGlobalScope()) { + $meta[CustomerInterface::WEBSITE_ID]['arguments']['data']['config']['isGlobalScope'] = 1; + } + + if (isset($meta[AddressInterface::COUNTRY_ID]) && !$this->getShareConfig()->isGlobalScope()) { + $meta[AddressInterface::COUNTRY_ID]['arguments']['data']['config']['filterBy'] = [ + 'target' => '${ $.provider }:data.customer.website_id', + 'field' => 'website_ids' + ]; + } + } + /** * Process attributes by frontend input type * * @param AttributeInterface $attribute * @param array $meta - * @return array + * @return void */ private function processFrontendInput(AttributeInterface $attribute, array &$meta) { @@ -250,4 +534,20 @@ protected function prepareAddressData($addressId, array &$addresses, array $cust $addresses[$addressId]['street'] = explode("\n", $addresses[$addressId]['street']); } } + + /** + * Get FileProcessorFactory instance + * + * @return FileProcessorFactory + * + * @deprecated + */ + private function getFileProcessorFactory() + { + if ($this->fileProcessorFactory === null) { + $this->fileProcessorFactory = ObjectManager::getInstance() + ->get(\Magento\Customer\Model\FileProcessorFactory::class); + } + return $this->fileProcessorFactory; + } } diff --git a/app/code/Magento/Customer/Model/Customer/Mapper.php b/app/code/Magento/Customer/Model/Customer/Mapper.php index 55ca61f088b06..feb6d00b91d48 100644 --- a/app/code/Magento/Customer/Model/Customer/Mapper.php +++ b/app/code/Magento/Customer/Model/Customer/Mapper.php @@ -1,6 +1,6 @@ customerRegistry = $customerRegistry; + $this->customerResourceModel = $customerResourceModel; + } + + /** + * Reset Authentication data for customer. + * + * @param int $customerId + * @return $this + */ + public function saveAuth($customerId) + { + $customerSecure = $this->customerRegistry->retrieveSecureData($customerId); + + $this->customerResourceModel->getConnection()->update( + $this->customerResourceModel->getTable('customer_entity'), + [ + 'failures_num' => $customerSecure->getData('failures_num'), + 'first_failure' => $customerSecure->getData('first_failure'), + 'lock_expires' => $customerSecure->getData('lock_expires'), + ], + $this->customerResourceModel->getConnection()->quoteInto('entity_id = ?', $customerId) + ); + + return $this; + } +} diff --git a/app/code/Magento/Customer/Model/CustomerExtractor.php b/app/code/Magento/Customer/Model/CustomerExtractor.php index 56e127def199e..f3180c1211524 100644 --- a/app/code/Magento/Customer/Model/CustomerExtractor.php +++ b/app/code/Magento/Customer/Model/CustomerExtractor.php @@ -1,11 +1,13 @@ formFactory->create('customer', $formCode); + public function extract( + $formCode, + RequestInterface $request, + array $attributeValues = [] + ) { + $customerForm = $this->formFactory->create( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + $formCode, + $attributeValues + ); + $customerData = $customerForm->extractData($request); + $customerData = $customerForm->compactData($customerData); + $allowedAttributes = $customerForm->getAllowedAttributes(); $isGroupIdEmpty = isset($allowedAttributes['group_id']); diff --git a/app/code/Magento/Customer/Model/CustomerManagement.php b/app/code/Magento/Customer/Model/CustomerManagement.php index b0d2f41dd0c41..8f58310043452 100644 --- a/app/code/Magento/Customer/Model/CustomerManagement.php +++ b/app/code/Magento/Customer/Model/CustomerManagement.php @@ -1,6 +1,6 @@ mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); + $this->uploaderFactory = $uploaderFactory; + $this->urlBuilder = $urlBuilder; + $this->urlEncoder = $urlEncoder; + $this->entityTypeCode = $entityTypeCode; + $this->mime = $mime; + $this->allowedExtensions = $allowedExtensions; + } + + /** + * Retrieve base64 encoded file content + * + * @param string $fileName + * @return string + */ + public function getBase64EncodedData($fileName) + { + $filePath = $this->entityTypeCode . '/' . ltrim($fileName, '/'); + + $fileContent = $this->mediaDirectory->readFile($filePath); + + $encodedContent = base64_encode($fileContent); + return $encodedContent; + } + + /** + * Get file statistics data + * + * @param string $fileName + * @return array + */ + public function getStat($fileName) + { + $filePath = $this->entityTypeCode . '/' . ltrim($fileName, '/'); + + $result = $this->mediaDirectory->stat($filePath); + return $result; + } + + /** + * Retrieve MIME type of requested file + * + * @param string $fileName + * @return string + */ + public function getMimeType($fileName) + { + $filePath = $this->entityTypeCode . '/' . ltrim($fileName, '/'); + $absoluteFilePath = $this->mediaDirectory->getAbsolutePath($filePath); + + $result = $this->mime->getMimeType($absoluteFilePath); + return $result; + } + + /** + * Check if the file exists + * + * @param string $fileName + * @return bool + */ + public function isExist($fileName) + { + $filePath = $this->entityTypeCode . '/' . ltrim($fileName, '/'); + + $result = $this->mediaDirectory->isExist($filePath); + return $result; + } + + /** + * Retrieve customer/index/viewfile action URL + * + * @param string $filePath + * @param string $type + * @return string + */ + public function getViewUrl($filePath, $type) + { + $viewUrl = ''; + + if ($this->entityTypeCode == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) { + $filePath = $this->entityTypeCode . '/' . ltrim($filePath, '/'); + $viewUrl = $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]) + . $this->mediaDirectory->getRelativePath($filePath); + } + + if ($this->entityTypeCode == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { + $viewUrl = $this->urlBuilder->getUrl( + 'customer/index/viewfile', + [$type => $this->urlEncoder->encode(ltrim($filePath, '/'))] + ); + } + + return $viewUrl; + } + + /** + * Save uploaded file to temporary directory + * + * @param string $fileId + * @return \string[] + * @throws LocalizedException + */ + public function saveTemporaryFile($fileId) + { + /** @var Uploader $uploader */ + $uploader = $this->uploaderFactory->create(['fileId' => $fileId]); + $uploader->setFilesDispersion(false); + $uploader->setFilenamesCaseSensitivity(false); + $uploader->setAllowRenameFiles(true); + $uploader->setAllowedExtensions($this->allowedExtensions); + + $path = $this->mediaDirectory->getAbsolutePath( + $this->entityTypeCode . '/' . self::TMP_DIR + ); + + $result = $uploader->save($path); + if (!$result) { + throw new LocalizedException(__('File can not be saved to the destination folder.')); + } + + return $result; + } + + /** + * Move file from temporary directory into base directory + * + * @param string $fileName + * @return string + * @throws LocalizedException + */ + public function moveTemporaryFile($fileName) + { + $fileName = ltrim($fileName, '/'); + + $dispersionPath = Uploader::getDispretionPath($fileName); + $destinationPath = $this->entityTypeCode . $dispersionPath; + + if (!$this->mediaDirectory->create($destinationPath)) { + throw new LocalizedException( + __('Unable to create directory %1.', $destinationPath) + ); + } + + if (!$this->mediaDirectory->isWritable($destinationPath)) { + throw new LocalizedException( + __('Destination folder is not writable or does not exists.') + ); + } + + $destinationFileName = Uploader::getNewFileName( + $this->mediaDirectory->getAbsolutePath($destinationPath) . '/' . $fileName + ); + + try { + $this->mediaDirectory->renameFile( + $this->entityTypeCode . '/' . self::TMP_DIR . '/' . $fileName, + $destinationPath . '/' . $destinationFileName + ); + } catch (\Exception $e) { + throw new LocalizedException( + __('Something went wrong while saving the file.') + ); + } + + $fileName = $dispersionPath . '/' . $fileName; + return $fileName; + } + + /** + * Remove uploaded file + * + * @param string $fileName + * @return bool + */ + public function removeUploadedFile($fileName) + { + $filePath = $this->entityTypeCode . '/' . ltrim($fileName, '/'); + + $result = $this->mediaDirectory->delete($filePath); + return $result; + } +} diff --git a/app/code/Magento/Customer/Model/FileUploader.php b/app/code/Magento/Customer/Model/FileUploader.php new file mode 100644 index 0000000000000..d6fb867af7fa6 --- /dev/null +++ b/app/code/Magento/Customer/Model/FileUploader.php @@ -0,0 +1,172 @@ +customerMetadataService = $customerMetadataService; + $this->addressMetadataService = $addressMetadataService; + $this->elementFactory = $elementFactory; + $this->fileProcessorFactory = $fileProcessorFactory; + $this->attributeMetadata = $attributeMetadata; + $this->entityTypeCode = $entityTypeCode; + $this->scope = $scope; + } + + /** + * Validate uploaded file + * + * @return array|bool + */ + public function validate() + { + $formElement = $this->elementFactory->create( + $this->attributeMetadata, + null, + $this->entityTypeCode + ); + + $errors = $formElement->validateValue($this->getData()); + return $errors; + } + + /** + * Execute file uploading + * + * @return \string[] + * @throws LocalizedException + */ + public function upload() + { + /** @var FileProcessor $fileProcessor */ + $fileProcessor = $this->fileProcessorFactory->create([ + 'entityTypeCode' => $this->entityTypeCode, + 'allowedExtensions' => $this->getAllowedExtensions(), + ]); + + $result = $fileProcessor->saveTemporaryFile($this->scope . '[' . $this->getAttributeCode() . ']'); + + // Update tmp_name param. Required for attribute validation! + $result['tmp_name'] = $result['path'] . '/' . ltrim($result['file'], '/'); + + $result['url'] = $fileProcessor->getViewUrl( + FileProcessor::TMP_DIR . '/' . ltrim($result['name'], '/'), + $this->attributeMetadata->getFrontendInput() + ); + + return $result; + } + + /** + * Get attribute code + * + * @return string + */ + private function getAttributeCode() + { + return key($_FILES[$this->scope]['name']); + } + + /** + * Retrieve data from global $_FILES array + * + * @return array + */ + private function getData() + { + $data = []; + + $fileAttributes = $_FILES[$this->scope]; + foreach ($fileAttributes as $attributeName => $attributeValue) { + $data[$attributeName] = $attributeValue[$this->getAttributeCode()]; + } + + return $data; + } + + /** + * Get allowed extensions + * + * @return array + */ + private function getAllowedExtensions() + { + $allowedExtensions = []; + + $validationRules = $this->attributeMetadata->getValidationRules(); + foreach ($validationRules as $validationRule) { + if ($validationRule->getName() == 'file_extensions') { + $allowedExtensions = explode(',', $validationRule->getValue()); + array_walk($allowedExtensions, function (&$value) { + $value = strtolower(trim($value)); + }); + break; + } + } + + return $allowedExtensions; + } +} diff --git a/app/code/Magento/Customer/Model/Form.php b/app/code/Magento/Customer/Model/Form.php index cfc88252f31ab..6e948e0b000ea 100644 --- a/app/code/Magento/Customer/Model/Form.php +++ b/app/code/Magento/Customer/Model/Form.php @@ -1,6 +1,6 @@ getIsAjaxRequest()) { - return false; - } - $extend = $this->_getRequestValue($request); $attrCode = $this->getAttribute()->getAttributeCode(); @@ -117,6 +127,14 @@ public function extractValue(\Magento\Framework\App\RequestInterface $request) $value[$fileKey] = $scopeData[$attrCode]; } } + } else if (isset($extend[0]['file']) && !empty($extend[0]['file'])) { + /** + * This case is required by file uploader UI component + * + * $extend[0]['file'] - uses for AJAX validation + * $extend[0] - uses for POST request + */ + $value = $this->getIsAjaxRequest() ? $extend[0]['file'] : $extend[0]; } else { $value = []; } @@ -194,7 +212,17 @@ protected function _validateByRules($value) */ protected function _isUploadedFile($filename) { - return is_uploaded_file($filename); + if (is_uploaded_file($filename)) { + return true; + } + + // This case is required for file uploader UI component + $temporaryFile = FileProcessor::TMP_DIR . '/' . pathinfo($filename)['basename']; + if ($this->getFileProcessor()->isExist($temporaryFile)) { + return true; + } + + return false; } /** @@ -241,7 +269,7 @@ public function validateValue($value) /** * {@inheritdoc} * - * @return $this|string + * @return ImageContentInterface|array|string|null */ public function compactValue($value) { @@ -249,11 +277,49 @@ public function compactValue($value) return $this; } - $attribute = $this->getAttribute(); - $original = $this->_value; + // Remove outdated file (in the case of file uploader UI component) + if (empty($value) && !empty($this->_value)) { + $this->getFileProcessor()->removeUploadedFile($this->_value); + return $value; + } + + if (isset($value['file']) && !empty($value['file'])) { + if ($value['file'] == $this->_value) { + return $this->_value; + } + $result = $this->processUiComponentValue($value); + } else { + $result = $this->processInputFieldValue($value); + } + + return $result; + } + + /** + * Process file uploader UI component data + * + * @param array $value + * @return string|null + */ + protected function processUiComponentValue(array $value) + { + $result = $this->getFileProcessor()->moveTemporaryFile($value['file']); + return $result; + } + + /** + * Process input type=file component data + * + * @param string $value + * @return bool|int|string + */ + protected function processInputFieldValue($value) + { $toDelete = false; - if ($original) { - if (!$attribute->isRequired() && !empty($value['delete'])) { + if ($this->_value) { + if (!$this->getAttribute()->isRequired() + && !empty($value['delete']) + ) { $toDelete = true; } if (!empty($value['tmp_name'])) { @@ -262,11 +328,11 @@ public function compactValue($value) } $mediaDir = $this->_fileSystem->getDirectoryWrite(DirectoryList::MEDIA); - $result = $original; - // unlink entity file + $result = $this->_value; + if ($toDelete) { + $mediaDir->delete($this->_entityTypeCode . '/' . ltrim($this->_value, '/')); $result = ''; - $mediaDir->delete($this->_entityTypeCode . $original); } if (!empty($value['tmp_name'])) { @@ -309,4 +375,37 @@ public function outputValue($format = \Magento\Customer\Model\Metadata\ElementFa return $output; } + + /** + * Get FileProcessor instance + * + * @return FileProcessor + * + * @deprecated + */ + protected function getFileProcessor() + { + if ($this->fileProcessor === null) { + $this->fileProcessor = $this->getFileProcessorFactory()->create([ + 'entityTypeCode' => $this->_entityTypeCode, + ]); + } + return $this->fileProcessor; + } + + /** + * Get FileProcessorFactory instance + * + * @return FileProcessorFactory + * + * @deprecated + */ + protected function getFileProcessorFactory() + { + if ($this->fileProcessorFactory === null) { + $this->fileProcessorFactory = ObjectManager::getInstance() + ->get('Magento\Customer\Model\FileProcessorFactory'); + } + return $this->fileProcessorFactory; + } } diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Hidden.php b/app/code/Magento/Customer/Model/Metadata/Form/Hidden.php index d29ce525e8e18..9d02ff295be8f 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/Hidden.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/Hidden.php @@ -2,7 +2,7 @@ /** * Form Element Hidden Data Model * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Model\Metadata\Form; diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Image.php b/app/code/Magento/Customer/Model/Metadata/Form/Image.php index b50a2d519f4e0..a1cad8464e11b 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/Image.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/Image.php @@ -2,15 +2,26 @@ /** * Form Element Image Data Model * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Model\Metadata\Form; +use Magento\Customer\Api\AddressMetadataInterface; +use Magento\Customer\Api\CustomerMetadataInterface; +use Magento\Customer\Model\FileProcessor; use Magento\Framework\Api\ArrayObjectSearch; +use Magento\Framework\Api\Data\ImageContentInterface; +use Magento\Framework\Api\Data\ImageContentInterfaceFactory; +use Magento\Framework\App\ObjectManager; class Image extends File { + /** + * @var ImageContentInterfaceFactory + */ + private $imageContentFactory; + /** * Validate file by attribute validate rules * Return array of errors @@ -68,7 +79,7 @@ protected function _validateByRules($value) $maxImageHeight = ArrayObjectSearch::getArrayElementByName( $rules, - 'max_image_height' + 'max_image_heght' ); if ($maxImageHeight !== null) { if ($maxImageHeight < $imageProp[1]) { @@ -79,4 +90,81 @@ protected function _validateByRules($value) return $errors; } + + /** + * Process file uploader UI component data + * + * @param array $value + * @return bool|int|ImageContentInterface|string + */ + protected function processUiComponentValue(array $value) + { + if ($this->_entityTypeCode == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) { + $result = $this->processCustomerAddressValue($value); + return $result; + } + + if ($this->_entityTypeCode == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { + $result = $this->processCustomerValue($value); + return $result; + } + + return $this->_value; + } + + /** + * Process file uploader UI component data for customer_address entity + * + * @param array $value + * @return string + */ + protected function processCustomerAddressValue(array $value) + { + $result = $this->getFileProcessor()->moveTemporaryFile($value['file']); + return $result; + } + + /** + * Process file uploader UI component data for customer entity + * + * @param array $value + * @return bool|int|ImageContentInterface|string + */ + protected function processCustomerValue(array $value) + { + $temporaryFile = FileProcessor::TMP_DIR . '/' . ltrim($value['file'], '/'); + + if ($this->getFileProcessor()->isExist($temporaryFile)) { + $base64EncodedData = $this->getFileProcessor()->getBase64EncodedData($temporaryFile); + + /** @var ImageContentInterface $imageContentDataObject */ + $imageContentDataObject = $this->getImageContentFactory()->create() + ->setName($value['name']) + ->setBase64EncodedData($base64EncodedData) + ->setType($value['type']); + + // Remove temporary file + $this->getFileProcessor()->removeUploadedFile($temporaryFile); + + return $imageContentDataObject; + } + + return $this->_value; + } + + /** + * Get ImageContentInterfaceFactory instance + * + * @return ImageContentInterfaceFactory + * + * @deprecated + */ + private function getImageContentFactory() + { + if ($this->imageContentFactory === null) { + $this->imageContentFactory = ObjectManager::getInstance() + ->get('Magento\Framework\Api\Data\ImageContentInterfaceFactory'); + } + return $this->imageContentFactory; + } } diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php b/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php index f9b80b6c0a48a..d9d7c1e71e6f1 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/Multiline.php @@ -2,7 +2,7 @@ /** * Form Element Multiline Data Model * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Model\Metadata\Form; diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Multiselect.php b/app/code/Magento/Customer/Model/Metadata/Form/Multiselect.php index a6c3b4b48eb28..cfa864e8fc679 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/Multiselect.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/Multiselect.php @@ -2,7 +2,7 @@ /** * Form Element Multiselect Data Model * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Model\Metadata\Form; diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php b/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php index 5d38d87f82e89..18e32e8992669 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php @@ -1,6 +1,6 @@ shareConfig = $share; + $this->storeManager = $storeManager; + } + + /** + * Retrieve all allowed countries or specific by scope depends on customer share setting + * + * @param \Magento\Directory\Model\AllowedCountries $subject + * @param string | null $filter + * @param string $scope + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeGetAllowedCountries( + \Magento\Directory\Model\AllowedCountries $subject, + $scope = ScopeInterface::SCOPE_WEBSITE, + $scopeCode = null + ) { + if ($this->shareConfig->isGlobalScope()) { + //Check if we have shared accounts - than merge all website allowed countries + $scopeCode = array_map(function (WebsiteInterface $website) { + return $website->getId(); + }, $this->storeManager->getWebsites()); + $scope = ScopeInterface::SCOPE_WEBSITES; + } + + return [$scope, $scopeCode]; + } +} diff --git a/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php b/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php index 971ced8b0373b..e45d292742ad7 100644 --- a/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php +++ b/app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php @@ -1,6 +1,6 @@ _options) { $this->_options = $this->_createCountriesCollection()->loadByStore( - $this->getAttribute()->getStoreId() + $this->getStoreResolver()->getCurrentStoreId() )->toOptionArray(); } return $this->_options; @@ -54,4 +62,19 @@ protected function _createCountriesCollection() { return $this->_countriesFactory->create(); } + + /** + * Retrieve Store Resolver + * + * @deprecated + * @return StoreResolverInterface + */ + private function getStoreResolver() + { + if (!$this->storeResolver) { + $this->storeResolver = ObjectManager::getInstance()->get(StoreResolverInterface::class); + } + + return $this->storeResolver; + } } diff --git a/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/CountryWithWebsites.php b/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/CountryWithWebsites.php new file mode 100644 index 0000000000000..1768e52d8affc --- /dev/null +++ b/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/CountryWithWebsites.php @@ -0,0 +1,116 @@ + + */ +namespace Magento\Customer\Model\ResourceModel\Address\Attribute\Source; + +use Magento\Customer\Model\Config\Share; +use Magento\Directory\Model\AllowedCountries; +use Magento\Store\Model\ScopeInterface; + +class CountryWithWebsites extends \Magento\Eav\Model\Entity\Attribute\Source\Table +{ + /** + * @var \Magento\Directory\Model\ResourceModel\Country\CollectionFactory + */ + private $countriesFactory; + + /** + * @var \Magento\Directory\Model\AllowedCountries + */ + private $allowedCountriesReader; + + /** + * @var array + */ + private $options; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + private $storeManager; + + /** + * @var Share + */ + private $shareConfig; + + /** + * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory + * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory + * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory + * @param AllowedCountries $allowedCountries + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param Share $shareConfig + */ + public function __construct( + \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory, + \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory, + \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory, + \Magento\Directory\Model\AllowedCountries $allowedCountries, + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Customer\Model\Config\Share $shareConfig + ) { + $this->countriesFactory = $countriesFactory; + $this->allowedCountriesReader = $allowedCountries; + $this->storeManager = $storeManager; + $this->shareConfig = $shareConfig; + parent::__construct($attrOptionCollectionFactory, $attrOptionFactory); + } + + /** + * Retrieve all options + * + * @return array + */ + public function getAllOptions() + { + if (!$this->options) { + $allowedCountries = []; + $websiteIds = []; + + if (!$this->shareConfig->isGlobalScope()) { + foreach ($this->storeManager->getWebsites() as $website) { + $countries = $this->allowedCountriesReader + ->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, $website->getId()); + $allowedCountries = array_merge($allowedCountries, $countries); + + foreach ($countries as $countryCode) { + $websiteIds[$countryCode][] = $website->getId(); + } + } + } else { + $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(); + } + + $this->options = $this->createCountriesCollection() + ->addFieldToFilter('country_id', ['in' => $allowedCountries]) + ->toOptionArray(); + + foreach ($this->options as &$option) { + if (isset($websiteIds[$option['value']])) { + $option['website_ids'] = $websiteIds[$option['value']]; + } + } + } + + return $this->options; + } + + /** + * Create Countries Collection with all countries + * + * @return \Magento\Directory\Model\ResourceModel\Country\Collection + */ + private function createCountriesCollection() + { + return $this->countriesFactory->create(); + } +} diff --git a/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/Region.php b/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/Region.php index 7c31248384245..0ab5a7dd0c120 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/Region.php +++ b/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/Region.php @@ -1,6 +1,6 @@ addressFactory->create(); $addressModel->updateData($address); $addressModel->setCustomer($customerModel); @@ -119,6 +120,7 @@ public function save(\Magento\Customer\Api\Data\AddressInterface $address) throw $inputException; } $addressModel->save(); + $address->setId($addressModel->getId()); // Clean up the customer registry since the Address save has a // side effect on customer : \Magento\Customer\Model\ResourceModel\Address::_afterSave $this->customerRegistry->remove($address->getCustomerId()); diff --git a/app/code/Magento/Customer/Model/ResourceModel/Attribute.php b/app/code/Magento/Customer/Model/ResourceModel/Attribute.php index f126b4401069b..2dfe24a351e45 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/Attribute.php +++ b/app/code/Magento/Customer/Model/ResourceModel/Attribute.php @@ -1,6 +1,6 @@ [ + 'entity_type_id' => \Magento\Customer\Api\CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER, 'entity_model' => 'Magento\Customer\Model\ResourceModel\Customer', 'attribute_model' => 'Magento\Customer\Model\Attribute', 'table' => 'customer_entity', @@ -338,6 +339,7 @@ public function getDefaultEntities() ], ], 'customer_address' => [ + 'entity_type_id' => \Magento\Customer\Api\AddressMetadataInterface::ATTRIBUTE_SET_ID_ADDRESS, 'entity_model' => 'Magento\Customer\Model\ResourceModel\Address', 'attribute_model' => 'Magento\Customer\Model\Attribute', 'table' => 'customer_address_entity', diff --git a/app/code/Magento/Customer/Setup/InstallData.php b/app/code/Magento/Customer/Setup/InstallData.php index 3c87be901389e..f3d8751584e41 100644 --- a/app/code/Magento/Customer/Setup/InstallData.php +++ b/app/code/Magento/Customer/Setup/InstallData.php @@ -1,6 +1,6 @@ upgradeCustomerPasswordResetlinkExpirationPeriodConfig($setup); } + if (version_compare($context->getVersion(), '2.0.9', '<')) { + $setup->getConnection()->beginTransaction(); + + try { + $this->migrateStoresAllowedCountriesToWebsite($setup); + $setup->getConnection()->commit(); + } catch (\Exception $e) { + $setup->getConnection()->rollBack(); + throw $e; + } + } + $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID); $indexer->reindexAll(); $this->eavConfig->clear(); $setup->endSetup(); } + /** + * Retrieve Store Manager + * + * @deprecated + * @return StoreManagerInterface + */ + private function getStoreManager() + { + if (!$this->storeManager) { + $this->storeManager = ObjectManager::getInstance()->get(StoreManagerInterface::class); + } + + return $this->storeManager; + } + + /** + * Retrieve Allowed Countries Reader + * + * @deprecated + * @return AllowedCountries + */ + private function getAllowedCountriesReader() + { + if (!$this->allowedCountriesReader) { + $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class); + } + + return $this->allowedCountriesReader; + } + + /** + * Merge allowed countries from different scopes + * + * @param array $countries + * @param array $newCountries + * @param string $identifier + * @return array + */ + private function mergeAllowedCountries(array $countries, array $newCountries, $identifier) + { + if (!isset($countries[$identifier])) { + $countries[$identifier] = $newCountries; + } else { + $countries[$identifier] = + array_replace($countries[$identifier], $newCountries); + } + + return $countries; + } + + /** + * Retrieve unqiue allowed countries by scope + * + * @param string $scope + * @param int $scopeCode + * @return array + */ + private function getAllowedCountries($scope, $scopeCode) + { + $allowedCountriesReader = $this->getAllowedCountriesReader(); + return $allowedCountriesReader->makeCountriesUnique( + $allowedCountriesReader->getCountriesFromConfig($scope, $scopeCode) + ); + } + + /** + * Migrate and merge allowed countries + * + * @param SetupInterface $setup + * @return void + */ + private function migrateStoresAllowedCountriesToWebsite(SetupInterface $setup) + { + + $allowedCountries = []; + //Process Websites + foreach ($this->getStoreManager()->getStores() as $store) { + $allowedCountries = $this->mergeAllowedCountries( + $allowedCountries, + $this->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store->getId()), + $store->getWebsiteId() + ); + } + //Process stores + foreach ($this->getStoreManager()->getWebsites() as $website) { + $allowedCountries = $this->mergeAllowedCountries( + $allowedCountries, + $this->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, $website->getId()), + $website->getId() + ); + } + + $connection = $setup->getConnection(); + + //Remove everything from stores scope + $connection->delete( + $setup->getTable('core_config_data'), + [ + 'path = ?' => AllowedCountries::ALLOWED_COUNTRIES_PATH, + 'scope = ?' => ScopeInterface::SCOPE_STORES + ] + ); + + //Update websites + foreach ($allowedCountries as $scopeId => $countries) { + $connection->update( + $setup->getTable('core_config_data'), + [ + 'value' => implode(',', $countries) + ], + [ + 'path = ?' => AllowedCountries::ALLOWED_COUNTRIES_PATH, + 'scope_id = ?' => $scopeId, + 'scope = ?' => ScopeInterface::SCOPE_WEBSITES + ] + ); + } + } + /** * @param array $entityAttributes * @param CustomerSetup $customerSetup diff --git a/app/code/Magento/Customer/Setup/UpgradeSchema.php b/app/code/Magento/Customer/Setup/UpgradeSchema.php index 18fc9b9f8d597..9ac21f1c98c26 100644 --- a/app/code/Magento/Customer/Setup/UpgradeSchema.php +++ b/app/code/Magento/Customer/Setup/UpgradeSchema.php @@ -1,6 +1,6 @@ prepareContext(); @@ -133,6 +138,10 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->customerMapperMock = $this->getMockBuilder('Magento\Customer\Model\Customer\Mapper') + ->disableOriginalConstructor() + ->getMock(); + $this->model = new EditPost( $this->context, $this->customerSession, @@ -141,16 +150,28 @@ protected function setUp() $this->validator, $this->customerExtractor ); - $reflection = new \ReflectionClass(get_class($this->model)); - $reflectionProperty = $reflection->getProperty('emailNotification'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->model, $this->emailNotification); - $reflectionProperty2 = $reflection->getProperty('scopeConfig'); - $reflectionProperty2->setAccessible(true); - $reflectionProperty2->setValue($this->model, $scopeConfigMock); - $reflectionProperty3 = $reflection->getProperty('authentication'); - $reflectionProperty3->setAccessible(true); - $reflectionProperty3->setValue($this->model, $this->authenticationMock); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $objectManager->setBackwardCompatibleProperty( + $this->model, + 'emailNotification', + $this->emailNotification + ); + $objectManager->setBackwardCompatibleProperty( + $this->model, + 'scopeConfig', + $scopeConfigMock + ); + $objectManager->setBackwardCompatibleProperty( + $this->model, + 'authentication', + $this->authenticationMock + ); + $objectManager->setBackwardCompatibleProperty( + $this->model, + 'customerMapper', + $this->customerMapperMock + ); } public function testInvalidFormKey() @@ -187,6 +208,9 @@ public function testNoPostValues() $this->assertSame($this->resultRedirect, $this->model->execute()); } + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function testGeneralSave() { $customerId = 1; @@ -203,6 +227,11 @@ public function testGeneralSave() ->method('getEmail') ->willReturn($customerEmail); + $this->customerMapperMock->expects($this->once()) + ->method('toFlatArray') + ->with($currentCustomerMock) + ->willReturn([]); + $this->customerSession->expects($this->once()) ->method('getCustomerId') ->willReturn($customerId); @@ -301,6 +330,11 @@ public function testChangeEmailException($testNumber, $exceptionClass, $errorMes $currentCustomerMock = $this->getCurrentCustomerMock($customerId, $address); $newCustomerMock = $this->getNewCustomerMock($customerId, $address); + $this->customerMapperMock->expects($this->once()) + ->method('toFlatArray') + ->with($currentCustomerMock) + ->willReturn([]); + $this->customerExtractor->expects($this->once()) ->method('extract') ->with('customer_account_edit', $this->request) @@ -409,6 +443,11 @@ public function testChangePassword( $currentCustomerMock = $this->getCurrentCustomerMock($customerId, $address); $newCustomerMock = $this->getNewCustomerMock($customerId, $address); + $this->customerMapperMock->expects($this->once()) + ->method('toFlatArray') + ->with($currentCustomerMock) + ->willReturn([]); + $this->customerSession->expects($this->once()) ->method('getCustomerId') ->willReturn($customerId); @@ -559,6 +598,11 @@ public function testGeneralException( $currentCustomerMock = $this->getCurrentCustomerMock($customerId, $address); $newCustomerMock = $this->getNewCustomerMock($customerId, $address); + $this->customerMapperMock->expects($this->once()) + ->method('toFlatArray') + ->with($currentCustomerMock) + ->willReturn([]); + $exception = new $exception(__($message)); $this->validator->expects($this->once()) diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPostTest.php index 8d176fe42628a..8873ab066d0b9 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/ForgotPasswordPostTest.php @@ -1,6 +1,6 @@ prepareContext(); @@ -197,6 +202,10 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->customerAddressMapper = $this->getMockBuilder('Magento\Customer\Model\Address\Mapper') + ->disableOriginalConstructor() + ->getMock(); + $this->model = new FormPost( $this->context, $this->session, @@ -212,6 +221,13 @@ protected function setUp() $this->regionFactory, $this->helperData ); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $objectManager->setBackwardCompatibleProperty( + $this->model, + 'customerAddressMapper', + $this->customerAddressMapper + ); } protected function prepareContext() @@ -458,22 +474,11 @@ public function testExecute( ->with($this->addressData) ->willReturnSelf(); - $this->dataProcessor->expects($this->once()) - ->method('buildOutputDataArray') - ->with($this->addressData, '\Magento\Customer\Api\Data\AddressInterface') + $this->customerAddressMapper->expects($this->once()) + ->method('toFlatArray') + ->with($this->addressData) ->willReturn($existingAddressData); - $this->addressData->expects($this->any()) - ->method('getRegion') - ->willReturn($this->regionData); - - $this->regionData->expects($this->once()) - ->method('getRegionCode') - ->willReturn($regionCode); - $this->regionData->expects($this->once()) - ->method('getRegion') - ->willReturn($region); - $this->formFactory->expects($this->once()) ->method('create') ->with('customer_address', 'customer_address_edit', $existingAddressData) diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/File/Address/UploadTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/File/Address/UploadTest.php new file mode 100644 index 0000000000000..56fc1dc99ee3d --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/File/Address/UploadTest.php @@ -0,0 +1,234 @@ +resultFactory = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->context = $this->getMockBuilder('Magento\Backend\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + + $this->context->expects($this->once()) + ->method('getResultFactory') + ->willReturn($this->resultFactory); + + $this->fileUploaderFactory = $this->getMockBuilder('Magento\Customer\Model\FileUploaderFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->addressMetadataService = $this->getMockBuilder('Magento\Customer\Api\AddressMetadataInterface') + ->getMockForAbstractClass(); + + $this->logger = $this->getMockBuilder('Psr\Log\LoggerInterface') + ->getMockForAbstractClass(); + + $this->controller = new Upload( + $this->context, + $this->fileUploaderFactory, + $this->addressMetadataService, + $this->logger + ); + } + + public function testExecuteEmptyFiles() + { + $exception = new \Exception('$_FILES array is empty.'); + $this->logger->expects($this->once()) + ->method('critical') + ->with($exception) + ->willReturnSelf(); + + $resultJson = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); + $resultJson->expects($this->once()) + ->method('setData') + ->with([ + 'error' => __('Something went wrong while saving file.'), + 'errorcode' => 0, + ]) + ->willReturnSelf(); + + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_JSON) + ->willReturn($resultJson); + + $this->assertInstanceOf('Magento\Framework\Controller\Result\Json', $this->controller->execute()); + } + + public function testExecute() + { + $attributeCode = 'attribute_code'; + + $_FILES = [ + 'address' => [ + 'name' => [ + 'new_0' => [ + $attributeCode => 'filename', + ], + ], + ], + ]; + + $resultFileName = '/filename.ext1'; + $resultFilePath = 'filepath'; + $resultFileUrl = 'viewFileUrl'; + + $result = [ + 'name' => $resultFileName, + 'file' => $resultFileName, + 'path' => $resultFilePath, + 'tmp_name' => $resultFilePath . $resultFileName, + 'url' => $resultFileUrl, + ]; + + $attributeMetadataMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') + ->getMockForAbstractClass(); + + $this->addressMetadataService->expects($this->once()) + ->method('getAttributeMetadata') + ->with($attributeCode) + ->willReturn($attributeMetadataMock); + + $fileUploader = $this->getMockBuilder('Magento\Customer\Model\FileUploader') + ->disableOriginalConstructor() + ->getMock(); + $fileUploader->expects($this->once()) + ->method('validate') + ->willReturn(true); + $fileUploader->expects($this->once()) + ->method('upload') + ->willReturn($result); + + $this->fileUploaderFactory->expects($this->once()) + ->method('create') + ->with([ + 'attributeMetadata' => $attributeMetadataMock, + 'entityTypeCode' => AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + 'scope' => 'address', + ]) + ->willReturn($fileUploader); + + $resultJson = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); + $resultJson->expects($this->once()) + ->method('setData') + ->with($result) + ->willReturnSelf(); + + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_JSON) + ->willReturn($resultJson); + + $this->assertInstanceOf('Magento\Framework\Controller\Result\Json', $this->controller->execute()); + } + + public function testExecuteWithErrors() + { + $attributeCode = 'attribute_code'; + + $_FILES = [ + 'address' => [ + 'name' => [ + 'new_0' => [ + $attributeCode => 'filename', + ], + ], + ], + ]; + + $errors = [ + 'error1', + 'error2', + ]; + + $attributeMetadataMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') + ->getMockForAbstractClass(); + + $this->addressMetadataService->expects($this->once()) + ->method('getAttributeMetadata') + ->with($attributeCode) + ->willReturn($attributeMetadataMock); + + $fileUploader = $this->getMockBuilder('Magento\Customer\Model\FileUploader') + ->disableOriginalConstructor() + ->getMock(); + $fileUploader->expects($this->once()) + ->method('validate') + ->willReturn($errors); + + $this->fileUploaderFactory->expects($this->once()) + ->method('create') + ->with([ + 'attributeMetadata' => $attributeMetadataMock, + 'entityTypeCode' => AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + 'scope' => 'address', + ]) + ->willReturn($fileUploader); + + $resultJson = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); + $resultJson->expects($this->once()) + ->method('setData') + ->with([ + 'error' => implode('
', $errors), + 'errorcode' => 0, + ]) + ->willReturnSelf(); + + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_JSON) + ->willReturn($resultJson); + + $this->assertInstanceOf('Magento\Framework\Controller\Result\Json', $this->controller->execute()); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/File/Customer/UploadTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/File/Customer/UploadTest.php new file mode 100644 index 0000000000000..3d5dfac3d0daa --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/File/Customer/UploadTest.php @@ -0,0 +1,230 @@ +resultFactory = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->context = $this->getMockBuilder('Magento\Backend\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + + $this->context->expects($this->once()) + ->method('getResultFactory') + ->willReturn($this->resultFactory); + + $this->fileUploaderFactory = $this->getMockBuilder('Magento\Customer\Model\FileUploaderFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->customerMetadataService = $this->getMockBuilder('Magento\Customer\Api\CustomerMetadataInterface') + ->getMockForAbstractClass(); + + $this->logger = $this->getMockBuilder('Psr\Log\LoggerInterface') + ->getMockForAbstractClass(); + + $this->controller = new Upload( + $this->context, + $this->fileUploaderFactory, + $this->customerMetadataService, + $this->logger + ); + } + + public function testExecuteEmptyFiles() + { + $exception = new \Exception('$_FILES array is empty.'); + $this->logger->expects($this->once()) + ->method('critical') + ->with($exception) + ->willReturnSelf(); + + $resultJson = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); + $resultJson->expects($this->once()) + ->method('setData') + ->with([ + 'error' => __('Something went wrong while saving file.'), + 'errorcode' => 0, + ]) + ->willReturnSelf(); + + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_JSON) + ->willReturn($resultJson); + + $this->assertInstanceOf('Magento\Framework\Controller\Result\Json', $this->controller->execute()); + } + + public function testExecute() + { + $attributeCode = 'attribute_code'; + + $_FILES = [ + 'customer' => [ + 'name' => [ + $attributeCode => 'filename', + ], + ], + ]; + + $resultFileName = '/filename.ext1'; + $resultFilePath = 'filepath'; + $resultFileUrl = 'viewFileUrl'; + + $result = [ + 'name' => $resultFileName, + 'file' => $resultFileName, + 'path' => $resultFilePath, + 'tmp_name' => $resultFilePath . $resultFileName, + 'url' => $resultFileUrl, + ]; + + $attributeMetadataMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') + ->getMockForAbstractClass(); + + $this->customerMetadataService->expects($this->once()) + ->method('getAttributeMetadata') + ->with($attributeCode) + ->willReturn($attributeMetadataMock); + + $fileUploader = $this->getMockBuilder('Magento\Customer\Model\FileUploader') + ->disableOriginalConstructor() + ->getMock(); + $fileUploader->expects($this->once()) + ->method('validate') + ->willReturn(true); + $fileUploader->expects($this->once()) + ->method('upload') + ->willReturn($result); + + $this->fileUploaderFactory->expects($this->once()) + ->method('create') + ->with([ + 'attributeMetadata' => $attributeMetadataMock, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'scope' => 'customer', + ]) + ->willReturn($fileUploader); + + $resultJson = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); + $resultJson->expects($this->once()) + ->method('setData') + ->with($result) + ->willReturnSelf(); + + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_JSON) + ->willReturn($resultJson); + + $this->assertInstanceOf('Magento\Framework\Controller\Result\Json', $this->controller->execute()); + } + + public function testExecuteWithErrors() + { + $attributeCode = 'attribute_code'; + + $_FILES = [ + 'customer' => [ + 'name' => [ + $attributeCode => 'filename', + ], + ], + ]; + + $errors = [ + 'error1', + 'error2', + ]; + + $attributeMetadataMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') + ->getMockForAbstractClass(); + + $this->customerMetadataService->expects($this->once()) + ->method('getAttributeMetadata') + ->with($attributeCode) + ->willReturn($attributeMetadataMock); + + $fileUploader = $this->getMockBuilder('Magento\Customer\Model\FileUploader') + ->disableOriginalConstructor() + ->getMock(); + $fileUploader->expects($this->once()) + ->method('validate') + ->willReturn($errors); + + $this->fileUploaderFactory->expects($this->once()) + ->method('create') + ->with([ + 'attributeMetadata' => $attributeMetadataMock, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'scope' => 'customer', + ]) + ->willReturn($fileUploader); + + $resultJson = $this->getMockBuilder('Magento\Framework\Controller\Result\Json') + ->disableOriginalConstructor() + ->getMock(); + $resultJson->expects($this->once()) + ->method('setData') + ->with([ + 'error' => implode('
', $errors), + 'errorcode' => 0, + ]) + ->willReturnSelf(); + + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_JSON) + ->willReturn($resultJson); + + $this->assertInstanceOf('Magento\Framework\Controller\Result\Json', $this->controller->execute()); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Group/SaveTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Group/SaveTest.php index e66ea71873b5b..b7361d045912d 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Group/SaveTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Group/SaveTest.php @@ -1,6 +1,6 @@ messageManager = $this->getMockBuilder( 'Magento\Framework\Message\Manager' )->disableOriginalConstructor()->setMethods( - ['addSuccess', 'addMessage', 'addException'] + ['addSuccess', 'addMessage', 'addException', 'addErrorMessage'] )->getMock(); $this->resultRedirectFactoryMock = $this->getMockBuilder('Magento\Backend\Model\View\Result\RedirectFactory') @@ -332,6 +332,56 @@ public function testResetPasswordActionCoreException() $this->_testedObject->execute(); } + public function testResetPasswordActionSecurityException() + { + $securityText = 'Security violation.'; + $exception = new \Magento\Framework\Exception\SecurityViolationException(__($securityText)); + $customerId = 1; + $email = 'some@example.com'; + $websiteId = 1; + + $this->_request->expects( + $this->once() + )->method( + 'getParam' + )->with( + $this->equalTo('customer_id'), + $this->equalTo(0) + )->will( + $this->returnValue($customerId) + ); + $customer = $this->getMockForAbstractClass( + \Magento\Customer\Api\Data\CustomerInterface::class, + ['getId', 'getEmail', 'getWebsiteId'] + ); + $customer->expects($this->once())->method('getEmail')->will($this->returnValue($email)); + $customer->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId)); + $this->_customerRepositoryMock->expects( + $this->once() + )->method( + 'getById' + )->with( + $customerId + )->will( + $this->returnValue($customer) + ); + $this->_customerAccountManagementMock->expects( + $this->once() + )->method( + 'initiatePasswordReset' + )->willThrowException($exception); + + $this->messageManager->expects( + $this->once() + )->method( + 'addErrorMessage' + )->with( + $this->equalTo($exception->getMessage()) + ); + + $this->_testedObject->execute(); + } + public function testResetPasswordActionCoreExceptionWarn() { $warningText = 'Warning'; diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php index 574f54cea931c..f7c90e6948881 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php @@ -1,13 +1,17 @@ customerRepositoryMock = $this->getMockBuilder('Magento\Customer\Api\CustomerRepositoryInterface') ->disableOriginalConstructor() ->getMock(); + $this->customerAddressRepositoryMock = $this->getMockBuilder('Magento\Customer\Api\AddressRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); $this->customerMapperMock = $this->getMockBuilder('Magento\Customer\Model\Customer\Mapper') ->disableOriginalConstructor() ->getMock(); + $this->customerAddressMapperMock = $this->getMockBuilder('Magento\Customer\Model\Address\Mapper') + ->disableOriginalConstructor() + ->getMock(); $this->dataHelperMock = $this->getMockBuilder('Magento\Framework\Api\DataObjectHelper') ->disableOriginalConstructor() ->getMock(); @@ -240,13 +260,16 @@ protected function setUp() 'authorization' => $this->authorizationMock, 'messageManager' => $this->messageManagerMock, 'resultRedirectFactory' => $this->redirectFactoryMock, + 'addressRepository' => $this->customerAddressRepositoryMock, + 'addressMapper' => $this->customerAddressMapperMock, ] ); - $refClass = new \ReflectionClass(Save::class); - $property = $refClass->getProperty('emailNotification'); - $property->setAccessible(true); - $property->setValue($this->model, $this->emailNotificationMock); + $objectManager->setBackwardCompatibleProperty( + $this->model, + 'emailNotification', + $this->emailNotificationMock + ); } /** @@ -279,13 +302,28 @@ public function testExecuteWithExistentCustomer() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ + 'entity_id' => $customerId, + 'code' => 'value', + 'coolness' => false, + 'disable_auto_group_change' => 'false', + ]; + $compactedData = [ 'entity_id' => $customerId, 'code' => 'value', 'coolness' => false, 'disable_auto_group_change' => 'false', + CustomerInterface::DEFAULT_BILLING => 2, + CustomerInterface::DEFAULT_SHIPPING => 2 ]; - $addressFilteredData = [ + $addressExtractedData = [ + 'entity_id' => $addressId, + 'code' => 'value', + 'coolness' => false, + 'region' => 'region', + 'region_id' => 'region_id', + ]; + $addressCompactedData = [ 'entity_id' => $addressId, 'default_billing' => 'true', 'default_shipping' => 'true', @@ -298,8 +336,13 @@ public function testExecuteWithExistentCustomer() 'entity_id' => $customerId, 'darkness' => true, 'name' => 'Name', - \Magento\Customer\Api\Data\CustomerInterface::DEFAULT_BILLING => false, - \Magento\Customer\Api\Data\CustomerInterface::DEFAULT_SHIPPING => false, + CustomerInterface::DEFAULT_BILLING => false, + CustomerInterface::DEFAULT_SHIPPING => false, + ]; + $savedAddressData = [ + 'entity_id' => $addressId, + 'default_billing' => true, + 'default_shipping' => true, ]; $mergedData = [ 'entity_id' => $customerId, @@ -307,8 +350,8 @@ public function testExecuteWithExistentCustomer() 'name' => 'Name', 'code' => 'value', 'disable_auto_group_change' => 0, - \Magento\Customer\Api\Data\CustomerInterface::DEFAULT_BILLING => $addressId, - \Magento\Customer\Api\Data\CustomerInterface::DEFAULT_SHIPPING => $addressId, + CustomerInterface::DEFAULT_BILLING => $addressId, + CustomerInterface::DEFAULT_SHIPPING => $addressId, 'confirmation' => false, 'sendemail_store_id' => '1', 'id' => $customerId, @@ -327,7 +370,7 @@ public function testExecuteWithExistentCustomer() 'id' => $addressId, ]; - /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $formMock */ + /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') ->disableOriginalConstructor() ->getMock(); @@ -339,9 +382,13 @@ public function testExecuteWithExistentCustomer() ->willReturn('int'); $attributes = [$attributeMock]; - $this->requestMock->expects($this->exactly(3)) + $this->requestMock->expects($this->any()) ->method('getPostValue') - ->willReturn($postValue); + ->willReturnMap([ + [null, null, $postValue], + [CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, null, $postValue['customer']], + ['address/' . $addressId, null, $postValue['address'][$addressId]], + ]); $this->requestMock->expects($this->exactly(3)) ->method('getPost') ->willReturnMap( @@ -352,69 +399,80 @@ public function testExecuteWithExistentCustomer() ] ); - /** @var \Magento\Customer\Model\Metadata\Form|\PHPUnit_Framework_MockObject_MockObject $formMock */ - $formMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') + /** @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject $objectMock */ + $objectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->disableOriginalConstructor() + ->getMock(); + $objectMock->expects($this->exactly(2)) + ->method('getData') + ->willReturnMap( + [ + ['customer', null, $postValue['customer']], + ['address/' . $addressId, null, $postValue['address'][$addressId]], + ] + ); + + $this->objectFactoryMock->expects($this->exactly(2)) + ->method('create') + ->with(['data' => $postValue]) + ->willReturn($objectMock); + + $customerFormMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') + ->disableOriginalConstructor() + ->getMock(); + $customerFormMock->expects($this->once()) + ->method('extractData') + ->with($this->requestMock, 'customer') + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) + ->method('compactData') + ->with($extractedData) + ->willReturn($compactedData); + $customerFormMock->expects($this->once()) + ->method('getAttributes') + ->willReturn($attributes); + + $customerAddressFormMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') ->disableOriginalConstructor() ->getMock(); + $customerAddressFormMock->expects($this->once()) + ->method('extractData') + ->with($this->requestMock, 'address/' . $addressId) + ->willReturn($addressExtractedData); + $customerAddressFormMock->expects($this->once()) + ->method('compactData') + ->with($addressExtractedData) + ->willReturn($addressCompactedData); + $customerAddressFormMock->expects($this->once()) + ->method('getAttributes') + ->willReturn($attributes); $this->formFactoryMock->expects($this->exactly(2)) ->method('create') ->willReturnMap( [ [ - \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'adminhtml_customer', - [], + $savedData, false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE, + Form::DONT_IGNORE_INVISIBLE, [], - $formMock + $customerFormMock ], [ - \Magento\Customer\Api\AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + AddressMetadataInterface::ENTITY_TYPE_ADDRESS, 'adminhtml_customer_address', - [], + $savedAddressData, false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE, + Form::DONT_IGNORE_INVISIBLE, [], - $formMock + $customerAddressFormMock ], ] ); - $formMock->expects($this->exactly(2)) - ->method('extractData') - ->willReturnMap( - [ - [$this->requestMock, 'customer', true, $filteredData], - [$this->requestMock, 'address/' . $addressId, true, $addressFilteredData], - ] - ); - - /** @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject $objectMock */ - $objectMock = $this->getMockBuilder('Magento\Framework\DataObject') - ->disableOriginalConstructor() - ->getMock(); - - $this->objectFactoryMock->expects($this->exactly(2)) - ->method('create') - ->with(['data' => $postValue]) - ->willReturn($objectMock); - - $objectMock->expects($this->exactly(2)) - ->method('getData') - ->willReturnMap( - [ - ['customer', null, $postValue['customer']], - ['address/' . $addressId, null, $postValue['address'][$addressId]], - ] - ); - - $formMock->expects($this->exactly(2)) - ->method('getAttributes') - ->willReturn($attributes); - - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ + /** @var CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') ->disableOriginalConstructor() ->getMock(); @@ -423,12 +481,12 @@ public function testExecuteWithExistentCustomer() ->method('create') ->willReturn($customerMock); - $this->customerRepositoryMock->expects($this->once()) + $this->customerRepositoryMock->expects($this->exactly(2)) ->method('getById') ->with($customerId) ->willReturn($customerMock); - $this->customerMapperMock->expects($this->once()) + $this->customerMapperMock->expects($this->exactly(2)) ->method('toFlatArray') ->with($customerMock) ->willReturn($savedData); @@ -437,6 +495,16 @@ public function testExecuteWithExistentCustomer() ->disableOriginalConstructor() ->getMock(); + $this->customerAddressRepositoryMock->expects($this->once()) + ->method('getById') + ->with($addressId) + ->willReturn($addressMock); + + $this->customerAddressMapperMock->expects($this->once()) + ->method('toFlatArray') + ->with($addressMock) + ->willReturn($savedAddressData); + $this->addressDataFactoryMock->expects($this->once()) ->method('create') ->willReturn($addressMock); @@ -504,7 +572,7 @@ public function testExecuteWithExistentCustomer() $this->registryMock->expects($this->once()) ->method('register') - ->with(\Magento\Customer\Controller\RegistryConstants::CURRENT_CUSTOMER_ID, $customerId); + ->with(RegistryConstants::CURRENT_CUSTOMER_ID, $customerId); $this->messageManagerMock->expects($this->once()) ->method('addSuccess') @@ -562,23 +630,21 @@ public function testExecuteWithNewCustomer() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - $addressFilteredData = [ + $addressExtractedData = [ 'entity_id' => $addressId, - 'default_billing' => 'false', - 'default_shipping' => 'false', - 'code' => 'value', + 'code' => 'value', 'coolness' => false, 'region' => 'region', 'region_id' => 'region_id', ]; $mergedData = [ 'disable_auto_group_change' => 0, - \Magento\Customer\Api\Data\CustomerInterface::DEFAULT_BILLING => null, - \Magento\Customer\Api\Data\CustomerInterface::DEFAULT_SHIPPING => null, + CustomerInterface::DEFAULT_BILLING => null, + CustomerInterface::DEFAULT_SHIPPING => null, 'confirmation' => false, ]; $mergedAddressData = [ @@ -595,7 +661,7 @@ public function testExecuteWithNewCustomer() 'id' => $addressId, ]; - /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $formMock */ + /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') ->disableOriginalConstructor() ->getMock(); @@ -607,9 +673,13 @@ public function testExecuteWithNewCustomer() ->willReturn('int'); $attributes = [$attributeMock]; - $this->requestMock->expects($this->exactly(3)) + $this->requestMock->expects($this->any()) ->method('getPostValue') - ->willReturn($postValue); + ->willReturnMap([ + [null, null, $postValue], + [CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, null, $postValue['customer']], + ['address/' . $addressId, null, $postValue['address'][$addressId]], + ]); $this->requestMock->expects($this->exactly(3)) ->method('getPost') ->willReturnMap( @@ -620,69 +690,80 @@ public function testExecuteWithNewCustomer() ] ); - /** @var \Magento\Customer\Model\Metadata\Form|\PHPUnit_Framework_MockObject_MockObject $formMock */ - $formMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') + /** @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject $objectMock */ + $objectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->disableOriginalConstructor() + ->getMock(); + $objectMock->expects($this->exactly(2)) + ->method('getData') + ->willReturnMap( + [ + ['customer', null, $postValue['customer']], + ['address/' . $addressId, null, $postValue['address'][$addressId]], + ] + ); + + $this->objectFactoryMock->expects($this->exactly(2)) + ->method('create') + ->with(['data' => $postValue]) + ->willReturn($objectMock); + + $customerFormMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') + ->disableOriginalConstructor() + ->getMock(); + $customerFormMock->expects($this->once()) + ->method('extractData') + ->with($this->requestMock, 'customer') + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) + ->method('compactData') + ->with($extractedData) + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) + ->method('getAttributes') + ->willReturn($attributes); + + $customerAddressFormMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') ->disableOriginalConstructor() ->getMock(); + $customerAddressFormMock->expects($this->once()) + ->method('extractData') + ->with($this->requestMock, 'address/' . $addressId) + ->willReturn($addressExtractedData); + $customerAddressFormMock->expects($this->once()) + ->method('compactData') + ->with($addressExtractedData) + ->willReturn($addressExtractedData); + $customerAddressFormMock->expects($this->once()) + ->method('getAttributes') + ->willReturn($attributes); $this->formFactoryMock->expects($this->exactly(2)) ->method('create') ->willReturnMap( [ [ - \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'adminhtml_customer', [], false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE, + Form::DONT_IGNORE_INVISIBLE, [], - $formMock + $customerFormMock ], [ - \Magento\Customer\Api\AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + AddressMetadataInterface::ENTITY_TYPE_ADDRESS, 'adminhtml_customer_address', [], false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE, + Form::DONT_IGNORE_INVISIBLE, [], - $formMock + $customerAddressFormMock ], ] ); - $formMock->expects($this->exactly(2)) - ->method('extractData') - ->willReturnMap( - [ - [$this->requestMock, 'customer', true, $filteredData], - [$this->requestMock, 'address/' . $addressId, true, $addressFilteredData], - ] - ); - - /** @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject $objectMock */ - $objectMock = $this->getMockBuilder('Magento\Framework\DataObject') - ->disableOriginalConstructor() - ->getMock(); - - $this->objectFactoryMock->expects($this->exactly(2)) - ->method('create') - ->with(['data' => $postValue]) - ->willReturn($objectMock); - - $objectMock->expects($this->exactly(2)) - ->method('getData') - ->willReturnMap( - [ - ['customer', null, $postValue['customer']], - ['address/' . $addressId, null, $postValue['address'][$addressId]], - ] - ); - - $formMock->expects($this->exactly(2)) - ->method('getAttributes') - ->willReturn($attributes); - - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ + /** @var CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') ->disableOriginalConstructor() ->getMock(); @@ -699,6 +780,16 @@ public function testExecuteWithNewCustomer() ->method('create') ->willReturn($addressMock); + $this->customerAddressRepositoryMock->expects($this->once()) + ->method('getById') + ->with($addressId) + ->willReturn($addressMock); + + $this->customerAddressMapperMock->expects($this->once()) + ->method('toFlatArray') + ->with($addressMock) + ->willReturn([]); + $this->dataHelperMock->expects($this->exactly(2)) ->method('populateWithArray') ->willReturnMap( @@ -753,7 +844,7 @@ public function testExecuteWithNewCustomer() $this->registryMock->expects($this->once()) ->method('register') - ->with(\Magento\Customer\Controller\RegistryConstants::CURRENT_CUSTOMER_ID, $customerId); + ->with(RegistryConstants::CURRENT_CUSTOMER_ID, $customerId); $this->messageManagerMock->expects($this->once()) ->method('addSuccess') @@ -796,12 +887,12 @@ public function testExecuteWithNewCustomerAndValidationException() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $formMock */ + /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') ->disableOriginalConstructor() ->getMock(); @@ -813,9 +904,12 @@ public function testExecuteWithNewCustomerAndValidationException() ->willReturn('int'); $attributes = [$attributeMock]; - $this->requestMock->expects($this->exactly(2)) + $this->requestMock->expects($this->any()) ->method('getPostValue') - ->willReturn($postValue); + ->willReturnMap([ + [null, null, $postValue], + [CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, null, $postValue['customer']], + ]); $this->requestMock->expects($this->exactly(2)) ->method('getPost') ->willReturnMap( @@ -825,46 +919,46 @@ public function testExecuteWithNewCustomerAndValidationException() ] ); - /** @var \Magento\Customer\Model\Metadata\Form|\PHPUnit_Framework_MockObject_MockObject $formMock */ - $formMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') - ->disableOriginalConstructor() - ->getMock(); - - $this->formFactoryMock->expects($this->once()) - ->method('create') - ->with( - \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, - 'adminhtml_customer', - [], - false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE - )->willReturn($formMock); - - $formMock->expects($this->once()) - ->method('extractData') - ->with($this->requestMock, 'customer') - ->willReturn($filteredData); - /** @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject $objectMock */ $objectMock = $this->getMockBuilder('Magento\Framework\DataObject') ->disableOriginalConstructor() ->getMock(); + $objectMock->expects($this->once()) + ->method('getData') + ->with('customer') + ->willReturn($postValue['customer']); $this->objectFactoryMock->expects($this->once()) ->method('create') ->with(['data' => $postValue]) ->willReturn($objectMock); - $objectMock->expects($this->once()) - ->method('getData') - ->with('customer') - ->willReturn($postValue['customer']); - - $formMock->expects($this->once()) + $customerFormMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') + ->disableOriginalConstructor() + ->getMock(); + $customerFormMock->expects($this->once()) + ->method('extractData') + ->with($this->requestMock, 'customer') + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) + ->method('compactData') + ->with($extractedData) + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ + $this->formFactoryMock->expects($this->once()) + ->method('create') + ->with( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'adminhtml_customer', + [], + false, + Form::DONT_IGNORE_INVISIBLE + )->willReturn($customerFormMock); + + /** @var CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') ->disableOriginalConstructor() ->getMock(); @@ -936,12 +1030,12 @@ public function testExecuteWithNewCustomerAndLocalizedException() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $formMock */ + /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') ->disableOriginalConstructor() ->getMock(); @@ -953,9 +1047,12 @@ public function testExecuteWithNewCustomerAndLocalizedException() ->willReturn('int'); $attributes = [$attributeMock]; - $this->requestMock->expects($this->exactly(2)) + $this->requestMock->expects($this->any()) ->method('getPostValue') - ->willReturn($postValue); + ->willReturnMap([ + [null, null, $postValue], + [CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, null, $postValue['customer']], + ]); $this->requestMock->expects($this->exactly(2)) ->method('getPost') ->willReturnMap( @@ -965,46 +1062,46 @@ public function testExecuteWithNewCustomerAndLocalizedException() ] ); - /** @var \Magento\Customer\Model\Metadata\Form|\PHPUnit_Framework_MockObject_MockObject $formMock */ - $formMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') - ->disableOriginalConstructor() - ->getMock(); - - $this->formFactoryMock->expects($this->once()) - ->method('create') - ->with( - \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, - 'adminhtml_customer', - [], - false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE - )->willReturn($formMock); - - $formMock->expects($this->once()) - ->method('extractData') - ->with($this->requestMock, 'customer') - ->willReturn($filteredData); - /** @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject $objectMock */ $objectMock = $this->getMockBuilder('Magento\Framework\DataObject') ->disableOriginalConstructor() ->getMock(); + $objectMock->expects($this->once()) + ->method('getData') + ->with('customer') + ->willReturn($postValue['customer']); $this->objectFactoryMock->expects($this->once()) ->method('create') ->with(['data' => $postValue]) ->willReturn($objectMock); - $objectMock->expects($this->once()) - ->method('getData') - ->with('customer') - ->willReturn($postValue['customer']); - - $formMock->expects($this->once()) + /** @var Form|\PHPUnit_Framework_MockObject_MockObject $formMock */ + $customerFormMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') + ->disableOriginalConstructor() + ->getMock(); + $customerFormMock->expects($this->once()) + ->method('extractData') + ->with($this->requestMock, 'customer') + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) + ->method('compactData') + ->with($extractedData) + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ + $this->formFactoryMock->expects($this->once()) + ->method('create') + ->with( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'adminhtml_customer', + [], + false, + Form::DONT_IGNORE_INVISIBLE + )->willReturn($customerFormMock); + $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') ->disableOriginalConstructor() ->getMock(); @@ -1076,12 +1173,12 @@ public function testExecuteWithNewCustomerAndException() ], 'subscription' => $subscription, ]; - $filteredData = [ + $extractedData = [ 'coolness' => false, 'disable_auto_group_change' => 'false', ]; - /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $formMock */ + /** @var AttributeMetadataInterface|\PHPUnit_Framework_MockObject_MockObject $customerFormMock */ $attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') ->disableOriginalConstructor() ->getMock(); @@ -1093,9 +1190,12 @@ public function testExecuteWithNewCustomerAndException() ->willReturn('int'); $attributes = [$attributeMock]; - $this->requestMock->expects($this->exactly(2)) + $this->requestMock->expects($this->any()) ->method('getPostValue') - ->willReturn($postValue); + ->willReturnMap([ + [null, null, $postValue], + [CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, null, $postValue['customer']], + ]); $this->requestMock->expects($this->exactly(2)) ->method('getPost') ->willReturnMap( @@ -1105,46 +1205,46 @@ public function testExecuteWithNewCustomerAndException() ] ); - /** @var \Magento\Customer\Model\Metadata\Form|\PHPUnit_Framework_MockObject_MockObject $formMock */ - $formMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') - ->disableOriginalConstructor() - ->getMock(); - - $this->formFactoryMock->expects($this->once()) - ->method('create') - ->with( - \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, - 'adminhtml_customer', - [], - false, - \Magento\Customer\Model\Metadata\Form::DONT_IGNORE_INVISIBLE - )->willReturn($formMock); - - $formMock->expects($this->once()) - ->method('extractData') - ->with($this->requestMock, 'customer') - ->willReturn($filteredData); - /** @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject $objectMock */ $objectMock = $this->getMockBuilder('Magento\Framework\DataObject') ->disableOriginalConstructor() ->getMock(); + $objectMock->expects($this->once()) + ->method('getData') + ->with('customer') + ->willReturn($postValue['customer']); $this->objectFactoryMock->expects($this->once()) ->method('create') ->with(['data' => $postValue]) ->willReturn($objectMock); - $objectMock->expects($this->once()) - ->method('getData') - ->with('customer') - ->willReturn($postValue['customer']); - - $formMock->expects($this->once()) + $customerFormMock = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form') + ->disableOriginalConstructor() + ->getMock(); + $customerFormMock->expects($this->once()) + ->method('extractData') + ->with($this->requestMock, 'customer') + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) + ->method('compactData') + ->with($extractedData) + ->willReturn($extractedData); + $customerFormMock->expects($this->once()) ->method('getAttributes') ->willReturn($attributes); - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ + $this->formFactoryMock->expects($this->once()) + ->method('create') + ->with( + CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'adminhtml_customer', + [], + false, + Form::DONT_IGNORE_INVISIBLE + )->willReturn($customerFormMock); + + /** @var CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ValidateTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ValidateTest.php index 979d41c13bfc5..6c971a6638152 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ValidateTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ValidateTest.php @@ -1,6 +1,6 @@ method('validateData') ->willReturn([$error]); - $this->extensibleDataObjectConverter->expects($this->once()) - ->method('toFlatArray') - ->willReturn([]); - $validationResult = $this->getMockForAbstractClass( 'Magento\Customer\Api\Data\ValidationResultsInterface', [], @@ -208,10 +204,6 @@ public function testExecuteWithoutAddresses() ->method('validateData') ->willReturn([$error]); - $this->extensibleDataObjectConverter->expects($this->once()) - ->method('toFlatArray') - ->willReturn([]); - $validationResult = $this->getMockForAbstractClass( 'Magento\Customer\Api\Data\ValidationResultsInterface', [], @@ -245,10 +237,6 @@ public function testExecuteWithException() $this->form->expects($this->never()) ->method('validateData'); - $this->extensibleDataObjectConverter->expects($this->once()) - ->method('toFlatArray') - ->willReturn([]); - $validationResult = $this->getMockForAbstractClass( 'Magento\Customer\Api\Data\ValidationResultsInterface', [], diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ViewfileTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ViewfileTest.php index 3586651d269d0..8ae444ab98eb1 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ViewfileTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ViewfileTest.php @@ -1,6 +1,6 @@ willReturnMap([['file', null, null], ['image', null, $decodedFile]]); $this->directoryMock->expects($this->once())->method('getAbsolutePath')->with($fileName)->willReturn($path); - $this->directoryMock->expects($this->once())->method('stat')->with($path)->willReturn($stat); + $this->directoryMock->expects($this->once())->method('stat')->with($fileName)->willReturn($stat); $this->fileSystemMock->expects($this->once())->method('getDirectoryRead') ->with(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA) diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Locks/UnlockTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Locks/UnlockTest.php index ed5609f40091d..1629b620328de 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Locks/UnlockTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Locks/UnlockTest.php @@ -1,6 +1,6 @@ jsonMock = $this->getMockBuilder(Json::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var JsonFactory|PHPUnit_Framework_MockObject_MockObject */ + $jsonFactoryMock = $this->getMockBuilder(JsonFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $jsonFactoryMock->expects($this->once())->method('create')->willReturn($this->jsonMock); + + $this->actionMock = $this->getMockBuilder(Load::class) + ->setConstructorArgs( + [ + $this->mockContext(), + $jsonFactoryMock, + $this->getMockBuilder(Identifier::class)->disableOriginalConstructor()->getMock(), + $this->getMockBuilder(SectionPoolInterface::class)->disableOriginalConstructor()->getMock() + ] + ) + ->setMethods(["getRequest"]) + ->getMock(); + } + + /** + * Test escaped response + * + * @dataProvider provideMessages + * + * @param string $message + * @param string $expectedMessage + */ + public function testEscapedResponse($message, $expectedMessage) + { + $this->jsonMock->expects($this->once()) + ->method('setData') + ->with(['message' => $expectedMessage]) + ->willReturnSelf(); + + /** @var RequestInterface|PHPUnit_Framework_MockObject_MockObject $request */ + $request = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->once())->method("getParam")->willThrowException(new \Exception($message)); + + $this->actionMock->expects($this->once())->method('getRequest')->willReturn($request); + $this->actionMock->execute(); + } + + /** + * @return array + */ + public function provideMessages() + { + return [ + ["test", "test"], + ["test", "test<script>alert()</script>"], + ]; + } + + /** + * @return Context|PHPUnit_Framework_MockObject_MockObject + */ + public function mockContext() + { + /** @var Context|PHPUnit_Framework_MockObject_MockObject $contextMock */ + $contextMock = $this->getMockBuilder(Context::class) + ->disableOriginalConstructor() + ->getMock(); + + $objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) + ->getMock(); + + $objectManagerMock->expects($this->once()) + ->method('get') + ->with(Escaper::class) + ->willReturn(new Escaper()); + + $contextMock->expects($this->once())->method('getObjectManager')->willReturn($objectManagerMock); + return $contextMock; + } +} diff --git a/app/code/Magento/Customer/Test/Unit/CustomerData/Plugin/SessionCheckerTest.php b/app/code/Magento/Customer/Test/Unit/CustomerData/Plugin/SessionCheckerTest.php index c2d22bb166c17..f6c269db70bae 100644 --- a/app/code/Magento/Customer/Test/Unit/CustomerData/Plugin/SessionCheckerTest.php +++ b/app/code/Magento/Customer/Test/Unit/CustomerData/Plugin/SessionCheckerTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php b/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php index 10c61358b143a..4349794d041fc 100644 --- a/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php +++ b/app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_one.xml b/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_one.xml index cbb32e5347cd2..fe42eff100fde 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_one.xml +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_one.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_two.xml b/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_two.xml index c5a18ed44d499..0b46b5291ec14 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_two.xml +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/Config/_files/formats_two.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php b/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php index 9dbec230b4321..0f73e340c4862 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php @@ -1,6 +1,6 @@ objectManager = new ObjectManagerHelper($this); + $this->backendConfigMock = $this->getMockBuilder(ConfigInterface::class) ->disableOriginalConstructor() ->setMethods(['getValue']) @@ -98,9 +110,11 @@ protected function setUp() false ); - $objectManagerHelper = new ObjectManagerHelper($this); + $this->customerAuthUpdate = $this->getMockBuilder(\Magento\Customer\Model\CustomerAuthUpdate::class) + ->disableOriginalConstructor() + ->getMock(); - $this->authentication = $objectManagerHelper->getObject( + $this->authentication = $this->objectManager->getObject( Authentication::class, [ 'customerRegistry' => $this->customerRegistryMock, @@ -110,6 +124,12 @@ protected function setUp() 'dateTime' => $this->dateTimeMock, ] ); + + $this->objectManager->setBackwardCompatibleProperty( + $this->authentication, + 'customerAuthUpdate', + $this->customerAuthUpdate + ); } public function testProcessAuthenticationFailureLockingIsDisabled() @@ -164,16 +184,10 @@ public function testProcessAuthenticationFailureFirstAttempt( ->method('retrieveSecureData') ->with($customerId) ->willReturn($this->customerSecureMock); - $customerMock = $this->getMockBuilder(CustomerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->customerRepositoryMock->expects($this->once()) - ->method('getById') + $this->customerAuthUpdate->expects($this->once()) + ->method('saveAuth') ->with($customerId) - ->willReturn($customerMock); - $this->customerRepositoryMock->expects($this->once()) - ->method('save') - ->with($customerMock); + ->willReturnSelf(); $this->customerSecureMock->expects($this->once())->method('getFailuresNum')->willReturn($failureNum); $this->customerSecureMock->expects($this->once()) @@ -210,16 +224,10 @@ public function testUnlock() ->method('retrieveSecureData') ->with($customerId) ->willReturn($this->customerSecureMock); - $customerMock = $this->getMockBuilder(CustomerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->customerRepositoryMock->expects($this->once()) - ->method('getById') + $this->customerAuthUpdate->expects($this->once()) + ->method('saveAuth') ->with($customerId) - ->willReturn($customerMock); - $this->customerRepositoryMock->expects($this->once()) - ->method('save') - ->with($customerMock); + ->willReturnSelf(); $this->customerSecureMock->expects($this->once())->method('setFailuresNum')->with(0); $this->customerSecureMock->expects($this->once())->method('setFirstFailure')->with(null); $this->customerSecureMock->expects($this->once())->method('setLockExpires')->with(null); @@ -312,9 +320,10 @@ public function testAuthenticate($result) ->with($customerId) ->willReturn($this->customerSecureMock); - $this->customerRepositoryMock->expects($this->once()) - ->method('save') - ->willReturn($customerMock); + $this->customerAuthUpdate->expects($this->once()) + ->method('saveAuth') + ->with($customerId) + ->willReturnSelf(); $this->setExpectedException('\Magento\Framework\Exception\InvalidEmailOrPasswordException'); $this->authentication->authenticate($customerId, $password); diff --git a/app/code/Magento/Customer/Test/Unit/Model/Authorization/CustomerSessionUserContextTest.php b/app/code/Magento/Customer/Test/Unit/Model/Authorization/CustomerSessionUserContextTest.php index 48b81bb83f00a..0cd11288d9698 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Authorization/CustomerSessionUserContextTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Authorization/CustomerSessionUserContextTest.php @@ -1,6 +1,6 @@ eavConfigMock = $this->getMockBuilder('Magento\Eav\Model\Config') + $this->eavConfigMock = $this->getMockBuilder(\Magento\Eav\Model\Config::class) ->disableOriginalConstructor() ->getMock(); $this->customerCollectionFactoryMock = $this->getMock( - 'Magento\Customer\Model\ResourceModel\Customer\CollectionFactory', + \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory::class, ['create'], [], '', false ); $this->eavValidationRulesMock = $this - ->getMockBuilder('Magento\Ui\DataProvider\EavValidationRules') + ->getMockBuilder(\Magento\Ui\DataProvider\EavValidationRules::class) ->disableOriginalConstructor() ->getMock(); $this->sessionMock = $this - ->getMockBuilder('Magento\Framework\Session\SessionManagerInterface') + ->getMockBuilder(\Magento\Framework\Session\SessionManagerInterface::class) ->setMethods(['getCustomerFormData', 'unsCustomerFormData']) ->getMockForAbstractClass(); + + $this->fileProcessor = $this->getMockBuilder(\Magento\Customer\Model\FileProcessor::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->fileProcessorFactory = $this->getMockBuilder(\Magento\Customer\Model\FileProcessorFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); } /** @@ -83,7 +104,7 @@ public function testGetAttributesMetaWithOptions(array $expected) { $helper = new ObjectManager($this); $dataProvider = $helper->getObject( - '\Magento\Customer\Model\Customer\DataProvider', + \Magento\Customer\Model\Customer\DataProvider::class, [ 'name' => 'test-name', 'primaryFieldName' => 'primary-field-name', @@ -94,6 +115,12 @@ public function testGetAttributesMetaWithOptions(array $expected) ] ); + $helper->setBackwardCompatibleProperty( + $dataProvider, + 'fileProcessorFactory', + $this->fileProcessorFactory + ); + $meta = $dataProvider->getMeta(); $this->assertNotEmpty($meta); $this->assertEquals($expected, $meta); @@ -212,7 +239,7 @@ public function getAttributesMetaDataProvider() */ protected function getCustomerCollectionFactoryMock() { - $collectionMock = $this->getMockBuilder('Magento\Customer\Model\ResourceModel\Customer\Collection') + $collectionMock = $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -249,7 +276,7 @@ protected function getEavConfigMock() */ protected function getTypeCustomerMock() { - $typeCustomerMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Type') + $typeCustomerMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Type::class) ->disableOriginalConstructor() ->getMock(); @@ -265,7 +292,7 @@ protected function getTypeCustomerMock() */ protected function getTypeAddressMock() { - $typeAddressMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Type') + $typeAddressMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Type::class) ->disableOriginalConstructor() ->getMock(); @@ -281,11 +308,11 @@ protected function getTypeAddressMock() */ protected function getAttributeMock() { - $attributeMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute') + $attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) ->setMethods(['getAttributeCode', 'getDataUsingMethod', 'usesSource', 'getSource']) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $sourceMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Source\AbstractSource') + $sourceMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\Source\AbstractSource::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); @@ -311,14 +338,14 @@ function ($origName) { ->method('getSource') ->willReturn($sourceMock); - $attributeBooleanMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute') + $attributeBooleanMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) ->setMethods(['getAttributeCode', 'getDataUsingMethod', 'usesSource', 'getFrontendInput']) ->disableOriginalConstructor() ->getMockForAbstractClass(); $attributeBooleanMock->expects($this->exactly(2)) ->method('getAttributeCode') ->willReturn('test-code-boolean'); - $attributeBooleanMock->expects($this->once()) + $attributeBooleanMock->expects($this->any()) ->method('getFrontendInput') ->willReturn('boolean'); $attributeBooleanMock->expects($this->any()) @@ -342,15 +369,50 @@ function ($origName) { return [$attributeMock, $attributeBooleanMock]; } + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function testGetData() { - $customer = $this->getMockBuilder('Magento\Customer\Model\Customer') + $customerId = 1; + $addressId = 2; + $customerData = [ + 'email' => 'test@test.ua', + 'default_billing' => $addressId, + 'default_shipping' => $addressId, + 'password_hash' => 'password_hash', + 'rp_token' => 'rp_token', + 'confirmation' => 'confirmation', + ]; + $customerDataFiltered = [ + 'email' => 'test@test.ua', + 'default_billing' => $addressId, + 'default_shipping' => $addressId + ]; + $addressData = [ + 'firstname' => 'firstname', + 'lastname' => 'lastname', + 'street' => "street\nstreet", + ]; + $expectedAddressData = [ + $addressId => [ + 'firstname' => 'firstname', + 'lastname' => 'lastname', + 'street' => [ + 'street', + 'street', + ], + 'default_billing' => $addressId, + 'default_shipping' => $addressId, + ] + ]; + $customer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) ->disableOriginalConstructor() ->getMock(); - $address = $this->getMockBuilder('Magento\Customer\Model\Address') + $address = $this->getMockBuilder(\Magento\Customer\Model\Address::class) ->disableOriginalConstructor() ->getMock(); - $collectionMock = $this->getMockBuilder('Magento\Customer\Model\ResourceModel\Customer\Collection') + $collectionMock = $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -367,32 +429,34 @@ public function testGetData() ->willReturn([$customer]); $customer->expects($this->once()) ->method('getData') - ->willReturn([ - 'email' => 'test@test.ua', - 'default_billing' => 2, - 'default_shipping' => 2, - ]); + ->willReturn($customerData); $customer->expects($this->once()) ->method('getAddresses') ->willReturn([$address]); + $customer->expects($this->once()) + ->method('getAttributes') + ->willReturn([]); + $customer->expects($this->once()) + ->method('getId') + ->willReturn($customerId); + $address->expects($this->atLeastOnce()) ->method('getId') - ->willReturn(2); + ->willReturn($addressId); $address->expects($this->once()) ->method('load') - ->with(2) + ->with($addressId) ->willReturnSelf(); $address->expects($this->once()) ->method('getData') - ->willReturn([ - 'firstname' => 'firstname', - 'lastname' => 'lastname', - 'street' => "street\nstreet", - ]); + ->willReturn($addressData); + $address->expects($this->once()) + ->method('getAttributes') + ->willReturn([]); $helper = new ObjectManager($this); $dataProvider = $helper->getObject( - '\Magento\Customer\Model\Customer\DataProvider', + \Magento\Customer\Model\Customer\DataProvider::class, [ 'name' => 'test-name', 'primaryFieldName' => 'primary-field-name', @@ -412,32 +476,30 @@ public function testGetData() ->method('getCustomerFormData') ->willReturn(null); + $helper->setBackwardCompatibleProperty( + $dataProvider, + 'fileProcessorFactory', + $this->fileProcessorFactory + ); + + $result = $dataProvider->getData(); + $this->assertArrayHasKey($customerId, $result); + $this->assertArrayHasKey('customer', $result[$customerId]); + $this->assertArrayHasKey('address', $result[$customerId]); + // assert that filtered fields are removed from the customer $this->assertEquals( - [ - '' => [ - 'customer' => [ - 'email' => 'test@test.ua', - 'default_billing' => 2, - 'default_shipping' => 2, - ], - 'address' => [ - 2 => [ - 'firstname' => 'firstname', - 'lastname' => 'lastname', - 'street' => [ - 'street', - 'street', - ], - 'default_billing' => 2, - 'default_shipping' => 2, - ] - ] - ] - ], - $dataProvider->getData() + $customerDataFiltered, + $result[$customerId]['customer'] + ); + $this->assertEquals( + $expectedAddressData, + $result[$customerId]['address'] ); } + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function testGetDataWithCustomerFormData() { $customerId = 11; @@ -462,13 +524,13 @@ public function testGetDataWithCustomerFormData() ], ]; - $customer = $this->getMockBuilder('Magento\Customer\Model\Customer') + $customer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) ->disableOriginalConstructor() ->getMock(); - $address = $this->getMockBuilder('Magento\Customer\Model\Address') + $address = $this->getMockBuilder(\Magento\Customer\Model\Address::class) ->disableOriginalConstructor() ->getMock(); - $collectionMock = $this->getMockBuilder('Magento\Customer\Model\ResourceModel\Customer\Collection') + $collectionMock = $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -496,6 +558,10 @@ public function testGetDataWithCustomerFormData() $customer->expects($this->once()) ->method('getAddresses') ->willReturn([$address]); + $customer->expects($this->once()) + ->method('getAttributes') + ->willReturn([]); + $address->expects($this->atLeastOnce()) ->method('getId') ->willReturn(2); @@ -510,10 +576,13 @@ public function testGetDataWithCustomerFormData() 'lastname' => 'lastname', 'street' => "street\nstreet", ]); + $address->expects($this->once()) + ->method('getAttributes') + ->willReturn([]); $helper = new ObjectManager($this); $dataProvider = $helper->getObject( - '\Magento\Customer\Model\Customer\DataProvider', + \Magento\Customer\Model\Customer\DataProvider::class, [ 'name' => 'test-name', 'primaryFieldName' => 'primary-field-name', @@ -535,6 +604,384 @@ public function testGetDataWithCustomerFormData() $this->sessionMock->expects($this->once()) ->method('unsCustomerFormData'); + $helper->setBackwardCompatibleProperty( + $dataProvider, + 'fileProcessorFactory', + $this->fileProcessorFactory + ); + $this->assertEquals([$customerId => $customerFormData], $dataProvider->getData()); } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testGetDataWithCustomAttributeImage() + { + $customerId = 1; + $customerEmail = 'user1@example.com'; + + $filename = '/filename.ext1'; + $viewUrl = 'viewUrl'; + + $expectedData = [ + $customerId => [ + 'customer' => [ + 'email' => $customerEmail, + 'img1' => [ + [ + 'file' => $filename, + 'size' => 1, + 'url' => $viewUrl, + 'name' => 'filename.ext1', + ], + ], + ], + ], + ]; + + $attributeMock = $this->getMockBuilder(\Magento\Customer\Model\Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + $attributeMock->expects($this->exactly(2)) + ->method('getFrontendInput') + ->willReturn('image'); + $attributeMock->expects($this->exactly(2)) + ->method('getAttributeCode') + ->willReturn('img1'); + + $entityTypeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Type::class) + ->disableOriginalConstructor() + ->getMock(); + $entityTypeMock->expects($this->once()) + ->method('getEntityTypeCode') + ->willReturn(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + + $customerMock = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) + ->disableOriginalConstructor() + ->getMock(); + $customerMock->expects($this->once()) + ->method('getData') + ->willReturn([ + 'email' => $customerEmail, + 'img1' => $filename, + ]); + $customerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([]); + $customerMock->expects($this->once()) + ->method('getId') + ->willReturn($customerId); + $customerMock->expects($this->once()) + ->method('getAttributes') + ->willReturn([$attributeMock]); + $customerMock->expects($this->once()) + ->method('getEntityType') + ->willReturn($entityTypeMock); + + $collectionMock = $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn([$customerMock]); + + $this->customerCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($collectionMock); + + $this->sessionMock->expects($this->once()) + ->method('getCustomerFormData') + ->willReturn([]); + + $this->fileProcessorFactory->expects($this->any()) + ->method('create') + ->with([ + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]) + ->willReturn($this->fileProcessor); + + $this->fileProcessor->expects($this->once()) + ->method('isExist') + ->with($filename) + ->willReturn(true); + $this->fileProcessor->expects($this->once()) + ->method('getStat') + ->with($filename) + ->willReturn(['size' => 1]); + $this->fileProcessor->expects($this->once()) + ->method('getViewUrl') + ->with('/filename.ext1', 'image') + ->willReturn($viewUrl); + + $objectManager = new ObjectManager($this); + $dataProvider = $objectManager->getObject( + \Magento\Customer\Model\Customer\DataProvider::class, + [ + 'name' => 'test-name', + 'primaryFieldName' => 'primary-field-name', + 'requestFieldName' => 'request-field-name', + 'eavValidationRules' => $this->eavValidationRulesMock, + 'customerCollectionFactory' => $this->customerCollectionFactoryMock, + 'eavConfig' => $this->getEavConfigMock() + ] + ); + + $objectManager->setBackwardCompatibleProperty( + $dataProvider, + 'session', + $this->sessionMock + ); + + $objectManager->setBackwardCompatibleProperty( + $dataProvider, + 'fileProcessorFactory', + $this->fileProcessorFactory + ); + + $this->assertEquals($expectedData, $dataProvider->getData()); + } + + public function testGetDataWithCustomAttributeImageNoData() + { + $customerId = 1; + $customerEmail = 'user1@example.com'; + + $expectedData = [ + $customerId => [ + 'customer' => [ + 'email' => $customerEmail, + 'img1' => [], + ], + ], + ]; + + $attributeMock = $this->getMockBuilder(\Magento\Customer\Model\Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + $attributeMock->expects($this->once()) + ->method('getFrontendInput') + ->willReturn('image'); + $attributeMock->expects($this->exactly(2)) + ->method('getAttributeCode') + ->willReturn('img1'); + + $entityTypeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Type::class) + ->disableOriginalConstructor() + ->getMock(); + $entityTypeMock->expects($this->once()) + ->method('getEntityTypeCode') + ->willReturn(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + + $customerMock = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) + ->disableOriginalConstructor() + ->getMock(); + $customerMock->expects($this->once()) + ->method('getData') + ->willReturn([ + 'email' => $customerEmail, + ]); + $customerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([]); + $customerMock->expects($this->once()) + ->method('getId') + ->willReturn($customerId); + $customerMock->expects($this->once()) + ->method('getAttributes') + ->willReturn([$attributeMock]); + $customerMock->expects($this->once()) + ->method('getEntityType') + ->willReturn($entityTypeMock); + + $collectionMock = $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn([$customerMock]); + + $this->customerCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($collectionMock); + + $this->sessionMock->expects($this->once()) + ->method('getCustomerFormData') + ->willReturn([]); + + $objectManager = new ObjectManager($this); + $dataProvider = $objectManager->getObject( + \Magento\Customer\Model\Customer\DataProvider::class, + [ + 'name' => 'test-name', + 'primaryFieldName' => 'primary-field-name', + 'requestFieldName' => 'request-field-name', + 'eavValidationRules' => $this->eavValidationRulesMock, + 'customerCollectionFactory' => $this->customerCollectionFactoryMock, + 'eavConfig' => $this->getEavConfigMock() + ] + ); + + $objectManager->setBackwardCompatibleProperty( + $dataProvider, + 'session', + $this->sessionMock + ); + + $objectManager->setBackwardCompatibleProperty( + $dataProvider, + 'fileProcessorFactory', + $this->fileProcessorFactory + ); + + $this->assertEquals($expectedData, $dataProvider->getData()); + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testGetAttributesMetaWithCustomAttributeImage() + { + $maxFileSize = 1000; + $allowedExtension = 'ext1 ext2'; + + $attributeCode = 'img1'; + + $collectionMock = $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Customer\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('addAttributeToSelect') + ->with('*'); + + $this->customerCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($collectionMock); + + $attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) + ->setMethods([ + 'getAttributeCode', + 'getFrontendInput', + 'getDataUsingMethod', + ]) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $attributeMock->expects($this->any()) + ->method('getAttributeCode') + ->willReturn($attributeCode); + $attributeMock->expects($this->any()) + ->method('getFrontendInput') + ->willReturn('image'); + $attributeMock->expects($this->any()) + ->method('getDataUsingMethod') + ->willReturnCallback( + function ($origName) { + return $origName; + } + ); + + $typeCustomerMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Type::class) + ->disableOriginalConstructor() + ->getMock(); + $typeCustomerMock->expects($this->once()) + ->method('getAttributeCollection') + ->willReturn([$attributeMock]); + $typeCustomerMock->expects($this->once()) + ->method('getEntityTypeCode') + ->willReturn(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + + $typeAddressMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Type::class) + ->disableOriginalConstructor() + ->getMock(); + $typeAddressMock->expects($this->once()) + ->method('getAttributeCollection') + ->willReturn([]); + + $this->eavConfigMock->expects($this->at(0)) + ->method('getEntityType') + ->with('customer') + ->willReturn($typeCustomerMock); + $this->eavConfigMock->expects($this->at(1)) + ->method('getEntityType') + ->with('customer_address') + ->willReturn($typeAddressMock); + + $this->eavValidationRulesMock->expects($this->once()) + ->method('build') + ->with($attributeMock, [ + 'dataType' => 'frontend_input', + 'formElement' => 'frontend_input', + 'visible' => 'is_visible', + 'required' => 'is_required', + 'sortOrder' => 'sort_order', + 'notice' => 'note', + 'default' => 'default_value', + 'size' => 'multiline_count', + 'label' => __('frontend_label'), + ]) + ->willReturn([ + 'max_file_size' => $maxFileSize, + 'file_extensions' => 'ext1, eXt2 ', // Added spaces and upper-cases + ]); + + $this->fileProcessorFactory->expects($this->any()) + ->method('create') + ->with([ + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]) + ->willReturn($this->fileProcessor); + + $objectManager = new ObjectManager($this); + $dataProvider = $objectManager->getObject( + \Magento\Customer\Model\Customer\DataProvider::class, + [ + 'name' => 'test-name', + 'primaryFieldName' => 'primary-field-name', + 'requestFieldName' => 'request-field-name', + 'eavValidationRules' => $this->eavValidationRulesMock, + 'customerCollectionFactory' => $this->customerCollectionFactoryMock, + 'eavConfig' => $this->eavConfigMock, + 'fileProcessorFactory' => $this->fileProcessorFactory, + ] + ); + + $result = $dataProvider->getMeta(); + + $this->assertNotEmpty($result); + + $expected = [ + 'customer' => [ + 'children' => [ + $attributeCode => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'formElement' => 'fileUploader', + 'componentType' => 'fileUploader', + 'maxFileSize' => $maxFileSize, + 'allowedExtensions' => $allowedExtension, + 'uploaderConfig' => [ + 'url' => 'customer/file/customer_upload', + ], + 'sortOrder' => 'sort_order', + 'required' => 'is_required', + 'visible' => 'is_visible', + 'validation' => [ + 'max_file_size' => $maxFileSize, + 'file_extensions' => 'ext1, eXt2 ', + ], + 'label' => __('frontend_label'), + ], + ], + ], + ], + ], + ], + 'address' => [ + 'children' => [], + ], + ]; + + $this->assertEquals($expected, $result); + } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php index 4e145d0f2898d..adeaaa6365796 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php @@ -1,6 +1,6 @@ objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->customerRegistry = + $this->getMock(\Magento\Customer\Model\CustomerRegistry::class, [], [], '', false); + $this->customerResourceModel = + $this->getMock(\Magento\Customer\Model\ResourceModel\Customer::class, [], [], '', false); + + $this->model = $this->objectManager->getObject( + \Magento\Customer\Model\CustomerAuthUpdate::class, + [ + 'customerRegistry' => $this->customerRegistry, + 'customerResourceModel' => $this->customerResourceModel, + ] + ); + } + + /** + * test SaveAuth + */ + public function testSaveAuth() + { + $customerId = 1; + + $customerSecureMock = $this->getMock( + \Magento\Customer\Model\Data\CustomerSecure::class, + [], + [], + '', + false + ); + + $dbAdapter = $this->getMock( + \Magento\Framework\DB\Adapter\AdapterInterface::class, + [], + [], + '', + false + ); + + $this->customerRegistry->expects($this->once()) + ->method('retrieveSecureData') + ->willReturn($customerSecureMock); + + $customerSecureMock->expects($this->exactly(3)) + ->method('getData') + ->willReturn(1); + + $this->customerResourceModel->expects($this->any()) + ->method('getConnection') + ->willReturn($dbAdapter); + + $this->customerResourceModel->expects($this->any()) + ->method('getTable') + ->willReturn('customer_entity'); + + $dbAdapter->expects($this->any()) + ->method('update') + ->with( + 'customer_entity', + [ + 'failures_num' => 1, + 'first_failure' => 1, + 'lock_expires' => 1 + ] + ); + + $dbAdapter->expects($this->any()) + ->method('quoteInto') + ->with( + 'entity_id = ?', + $customerId + ); + + $this->model->saveAuth($customerId); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/CustomerExtractorTest.php b/app/code/Magento/Customer/Test/Unit/Model/CustomerExtractorTest.php index c414d648b2172..311016b4c7db7 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/CustomerExtractorTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/CustomerExtractorTest.php @@ -1,6 +1,6 @@ method('extractData') ->with($this->request) ->willReturn($customerData); + $this->customerForm->expects($this->once()) + ->method('compactData') + ->with($customerData) + ->willReturn($customerData); $this->customerForm->expects($this->once()) ->method('getAllowedAttributes') ->willReturn(['group_id' => 'attribute object']); diff --git a/app/code/Magento/Customer/Test/Unit/Model/CustomerManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/CustomerManagementTest.php index 7253448df068f..6266013bc23de 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/CustomerManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/CustomerManagementTest.php @@ -1,6 +1,6 @@ mediaDirectory = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\WriteInterface') + ->getMockForAbstractClass(); + + $this->filesystem = $this->getMockBuilder('Magento\Framework\Filesystem') + ->disableOriginalConstructor() + ->getMock(); + $this->filesystem->expects($this->any()) + ->method('getDirectoryWrite') + ->with(DirectoryList::MEDIA) + ->willReturn($this->mediaDirectory); + + $this->uploaderFactory = $this->getMockBuilder('Magento\MediaStorage\Model\File\UploaderFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->urlBuilder = $this->getMockBuilder('Magento\Framework\UrlInterface') + ->getMockForAbstractClass(); + + $this->urlEncoder = $this->getMockBuilder('Magento\Framework\Url\EncoderInterface') + ->getMockForAbstractClass(); + + $this->mime = $this->getMockBuilder(\Magento\Framework\File\Mime::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function getModel($entityTypeCode, array $allowedExtensions = []) + { + $model = new FileProcessor( + $this->filesystem, + $this->uploaderFactory, + $this->urlBuilder, + $this->urlEncoder, + $entityTypeCode, + $this->mime, + $allowedExtensions + ); + return $model; + } + + public function testGetStat() + { + $fileName = '/filename.ext1'; + + $this->mediaDirectory->expects($this->once()) + ->method('stat') + ->with(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . $fileName) + ->willReturn(['size' => 1]); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $result = $model->getStat($fileName); + + $this->assertTrue(is_array($result)); + $this->assertArrayHasKey('size', $result); + $this->assertEquals(1, $result['size']); + } + + public function testIsExist() + { + $fileName = '/filename.ext1'; + + $this->mediaDirectory->expects($this->once()) + ->method('isExist') + ->with(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . $fileName) + ->willReturn(true); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $this->assertTrue($model->isExist($fileName)); + } + + public function testGetViewUrlCustomer() + { + $filePath = 'filename.ext1'; + $encodedFilePath = 'encodedfilenameext1'; + + $fileUrl = 'fileUrl'; + + $this->urlEncoder->expects($this->once()) + ->method('encode') + ->with($filePath) + ->willReturn($encodedFilePath); + + $this->urlBuilder->expects($this->once()) + ->method('getUrl') + ->with('customer/index/viewfile', ['image' => $encodedFilePath]) + ->willReturn($fileUrl); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $this->assertEquals($fileUrl, $model->getViewUrl($filePath, 'image')); + } + + public function testGetViewUrlCustomerAddress() + { + $filePath = 'filename.ext1'; + + $baseUrl = 'baseUrl'; + $relativeUrl = 'relativeUrl'; + + $this->urlBuilder->expects($this->once()) + ->method('getBaseUrl') + ->with(['_type' => \Magento\Framework\UrlInterface::URL_TYPE_MEDIA]) + ->willReturn($baseUrl); + + $this->mediaDirectory->expects($this->once()) + ->method('getRelativePath') + ->with(AddressMetadataInterface::ENTITY_TYPE_ADDRESS . '/' . $filePath) + ->willReturn($relativeUrl); + + $model = $this->getModel(AddressMetadataInterface::ENTITY_TYPE_ADDRESS); + $this->assertEquals($baseUrl . $relativeUrl, $model->getViewUrl($filePath, 'image')); + } + + public function testRemoveUploadedFile() + { + $fileName = '/filename.ext1'; + + $this->mediaDirectory->expects($this->once()) + ->method('delete') + ->with(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . $fileName) + ->willReturn(true); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $this->assertTrue($model->removeUploadedFile($fileName)); + } + + public function testSaveTemporaryFile() + { + $attributeCode = 'img1'; + + $allowedExtensions = [ + 'ext1', + 'ext2', + ]; + + $absolutePath = '/absolute/filepath'; + + $expectedResult = [ + 'file' => 'filename.ext1', + 'path' => 'filepath', + ]; + + $uploaderMock = $this->getMockBuilder('Magento\MediaStorage\Model\File\Uploader') + ->disableOriginalConstructor() + ->getMock(); + $uploaderMock->expects($this->once()) + ->method('setFilesDispersion') + ->with(false) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setFilenamesCaseSensitivity') + ->with(false) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setAllowRenameFiles') + ->with(true) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setAllowedExtensions') + ->with($allowedExtensions) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('save') + ->with($absolutePath) + ->willReturn($expectedResult); + + $this->uploaderFactory->expects($this->once()) + ->method('create') + ->with(['fileId' => 'customer[' . $attributeCode . ']']) + ->willReturn($uploaderMock); + + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . FileProcessor::TMP_DIR) + ->willReturn($absolutePath); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, $allowedExtensions); + $result = $model->saveTemporaryFile('customer[' . $attributeCode . ']'); + + $this->assertEquals($expectedResult, $result); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage File can not be saved to the destination folder. + */ + public function testSaveTemporaryFileWithError() + { + $attributeCode = 'img1'; + + $allowedExtensions = [ + 'ext1', + 'ext2', + ]; + + $absolutePath = '/absolute/filepath'; + + $uploaderMock = $this->getMockBuilder('Magento\MediaStorage\Model\File\Uploader') + ->disableOriginalConstructor() + ->getMock(); + $uploaderMock->expects($this->once()) + ->method('setFilesDispersion') + ->with(false) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setFilenamesCaseSensitivity') + ->with(false) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setAllowRenameFiles') + ->with(true) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setAllowedExtensions') + ->with($allowedExtensions) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('save') + ->with($absolutePath) + ->willReturn(false); + + $this->uploaderFactory->expects($this->once()) + ->method('create') + ->with(['fileId' => 'customer[' . $attributeCode . ']']) + ->willReturn($uploaderMock); + + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . FileProcessor::TMP_DIR) + ->willReturn($absolutePath); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, $allowedExtensions); + $model->saveTemporaryFile('customer[' . $attributeCode . ']'); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Unable to create directory customer/f/i + */ + public function testMoveTemporaryFileUnableToCreateDirectory() + { + $filePath = '/filename.ext1'; + + $destinationPath = 'customer/f/i'; + + $this->mediaDirectory->expects($this->once()) + ->method('create') + ->with($destinationPath) + ->willReturn(false); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $model->moveTemporaryFile($filePath); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Destination folder is not writable or does not exists + */ + public function testMoveTemporaryFileDestinationFolderDoesNotExists() + { + $filePath = '/filename.ext1'; + + $destinationPath = 'customer/f/i'; + + $this->mediaDirectory->expects($this->once()) + ->method('create') + ->with($destinationPath) + ->willReturn(true); + $this->mediaDirectory->expects($this->once()) + ->method('isWritable') + ->with($destinationPath) + ->willReturn(false); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $model->moveTemporaryFile($filePath); + } + + public function testMoveTemporaryFile() + { + $filePath = '/filename.ext1'; + + $destinationPath = 'customer/f/i'; + + $this->mediaDirectory->expects($this->once()) + ->method('create') + ->with($destinationPath) + ->willReturn(true); + $this->mediaDirectory->expects($this->once()) + ->method('isWritable') + ->with($destinationPath) + ->willReturn(true); + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with($destinationPath) + ->willReturn('/' . $destinationPath); + + $path = CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . FileProcessor::TMP_DIR . $filePath; + $newPath = $destinationPath . $filePath; + + $this->mediaDirectory->expects($this->once()) + ->method('renameFile') + ->with($path, $newPath) + ->willReturn(true); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $this->assertEquals('/f/i' . $filePath, $model->moveTemporaryFile($filePath)); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Something went wrong while saving the file + */ + public function testMoveTemporaryFileWithException() + { + $filePath = '/filename.ext1'; + + $destinationPath = 'customer/f/i'; + + $this->mediaDirectory->expects($this->once()) + ->method('create') + ->with($destinationPath) + ->willReturn(true); + $this->mediaDirectory->expects($this->once()) + ->method('isWritable') + ->with($destinationPath) + ->willReturn(true); + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with($destinationPath) + ->willReturn('/' . $destinationPath); + + $path = CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . FileProcessor::TMP_DIR . $filePath; + $newPath = $destinationPath . $filePath; + + $this->mediaDirectory->expects($this->once()) + ->method('renameFile') + ->with($path, $newPath) + ->willThrowException(new \Exception('Exception.')); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + $model->moveTemporaryFile($filePath); + } + + public function testGetMimeType() + { + $fileName = '/filename.ext1'; + $absoluteFilePath = '/absolute_path/customer/filename.ext1'; + + $expected = 'ext1'; + + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . ltrim($fileName, '/')) + ->willReturn($absoluteFilePath); + + $this->mime->expects($this->once()) + ->method('getMimeType') + ->with($absoluteFilePath) + ->willReturn($expected); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + + $this->assertEquals($expected, $model->getMimeType($fileName)); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/FileUploaderTest.php b/app/code/Magento/Customer/Test/Unit/Model/FileUploaderTest.php new file mode 100644 index 0000000000000..225207592694e --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Model/FileUploaderTest.php @@ -0,0 +1,185 @@ +customerMetadataService = $this->getMockBuilder('Magento\Customer\Api\CustomerMetadataInterface') + ->getMockForAbstractClass(); + + $this->addressMetadataService = $this->getMockBuilder('Magento\Customer\Api\AddressMetadataInterface') + ->getMockForAbstractClass(); + + $this->elementFactory = $this->getMockBuilder('Magento\Customer\Model\Metadata\ElementFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->fileProcessorFactory = $this->getMockBuilder('Magento\Customer\Model\FileProcessorFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->attributeMetadata = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface') + ->getMockForAbstractClass(); + } + + /** + * @param string $entityTypeCode + * @param string $scope + * @return FileUploader + */ + private function getModel($entityTypeCode, $scope) + { + $model = new FileUploader( + $this->customerMetadataService, + $this->addressMetadataService, + $this->elementFactory, + $this->fileProcessorFactory, + $this->attributeMetadata, + $entityTypeCode, + $scope + ); + return $model; + } + + public function testValidate() + { + $attributeCode = 'attribute_code'; + + $filename = 'filename.ext1'; + + $_FILES = [ + 'customer' => [ + 'name' => [ + $attributeCode => $filename, + ], + ], + ]; + + $formElement = $this->getMockBuilder('Magento\Customer\Model\Metadata\Form\Image') + ->disableOriginalConstructor() + ->getMock(); + $formElement->expects($this->once()) + ->method('validateValue') + ->with(['name' => $filename]) + ->willReturn(true); + + $this->elementFactory->expects($this->once()) + ->method('create') + ->with($this->attributeMetadata, null, CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) + ->willReturn($formElement); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'customer'); + $this->assertTrue($model->validate()); + } + + public function testUpload() + { + $attributeCode = 'attribute_code'; + $attributeFrontendInput = 'image'; + + $resultFileName = '/filename.ext1'; + $resultFilePath = 'filepath'; + $resultFileUrl = 'viewFileUrl'; + + $allowedExtensions = 'ext1,EXT2 , eXt3'; // Added spaces, commas and upper-cases + $expectedAllowedExtensions = [ + 'ext1', + 'ext2', + 'ext3', + ]; + + $_FILES = [ + 'customer' => [ + 'name' => [ + $attributeCode => 'filename', + ], + ], + ]; + + $expectedResult = [ + 'name' => $resultFileName, + 'file' => $resultFileName, + 'path' => $resultFilePath, + 'tmp_name' => $resultFilePath . $resultFileName, + 'url' => $resultFileUrl, + ]; + + $fileProcessor = $this->getMockBuilder('Magento\Customer\Model\FileProcessor') + ->disableOriginalConstructor() + ->getMock(); + $fileProcessor->expects($this->once()) + ->method('saveTemporaryFile') + ->with('customer[' . $attributeCode . ']') + ->willReturn([ + 'name' => $resultFileName, + 'path' => $resultFilePath, + 'file' => $resultFileName, + ]); + $fileProcessor->expects($this->once()) + ->method('getViewUrl') + ->with(FileProcessor::TMP_DIR . '/filename.ext1', $attributeFrontendInput) + ->willReturn($resultFileUrl); + + $this->fileProcessorFactory->expects($this->once()) + ->method('create') + ->with([ + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + 'allowedExtensions' => $expectedAllowedExtensions, + ]) + ->willReturn($fileProcessor); + + $validationRuleMock = $this->getMockBuilder('Magento\Customer\Api\Data\ValidationRuleInterface') + ->getMockForAbstractClass(); + $validationRuleMock->expects($this->once()) + ->method('getName') + ->willReturn('file_extensions'); + $validationRuleMock->expects($this->once()) + ->method('getValue') + ->willReturn($allowedExtensions); + + $this->attributeMetadata->expects($this->once()) + ->method('getFrontendInput') + ->willReturn($attributeFrontendInput); + $this->attributeMetadata->expects($this->once()) + ->method('getValidationRules') + ->willReturn([$validationRuleMock]); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'customer'); + $this->assertEquals($expectedResult, $model->upload()); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/GroupRegistryTest.php b/app/code/Magento/Customer/Test/Unit/Model/GroupRegistryTest.php index 4fe2efed4c0f1..98b32ffdeee1f 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/GroupRegistryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/GroupRegistryTest.php @@ -1,6 +1,6 @@ requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http') ->disableOriginalConstructor()->getMock(); $this->uploaderFactoryMock = $this->getMock('Magento\Framework\File\UploaderFactory', [], [], '', false); + + $this->fileProcessorMock = $this->getMockBuilder('Magento\Customer\Model\FileProcessor') + ->disableOriginalConstructor() + ->getMock(); } /** @@ -52,10 +63,9 @@ protected function setUp() * @param string $delete * @dataProvider extractValueNoRequestScopeDataProvider */ - public function testExtractValueNoRequestScope($expected, $attributeCode = '', $isAjax = false, $delete = '') + public function testExtractValueNoRequestScope($expected, $attributeCode = '', $delete = '') { $value = 'value'; - $fileForm = $this->getClass($value, $isAjax); $this->requestMock->expects( $this->any() @@ -75,7 +85,14 @@ public function testExtractValueNoRequestScope($expected, $attributeCode = '', $ if (!empty($attributeCode)) { $_FILES[$attributeCode] = ['attributeCodeValue']; } - $this->assertEquals($expected, $fileForm->extractValue($this->requestMock)); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertEquals($expected, $model->extractValue($this->requestMock)); if (!empty($attributeCode)) { unset($_FILES[$attributeCode]); } @@ -84,11 +101,10 @@ public function testExtractValueNoRequestScope($expected, $attributeCode = '', $ public function extractValueNoRequestScopeDataProvider() { return [ - 'ajax' => [false, '', true], 'no_file' => [[]], - 'delete' => [['delete' => true], '', false, true], - 'file_delete' => [['attributeCodeValue', 'delete' => true], 'attributeCode', false, true], - 'file_!delete' => [['attributeCodeValue'], 'attributeCode', false, false] + 'delete' => [['delete' => true], '', true], + 'file_delete' => [['attributeCodeValue', 'delete' => true], 'attributeCode', true], + 'file_!delete' => [['attributeCodeValue'], 'attributeCode', false] ]; } @@ -101,7 +117,6 @@ public function extractValueNoRequestScopeDataProvider() public function testExtractValueWithRequestScope($expected, $requestScope, $mainScope = false) { $value = 'value'; - $fileForm = $this->getClass($value, false); $this->requestMock->expects( $this->any() @@ -126,12 +141,18 @@ public function testExtractValueWithRequestScope($expected, $requestScope, $main $this->returnValue('attributeCode') ); - $fileForm->setRequestScope($requestScope); + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $model->setRequestScope($requestScope); if ($mainScope) { $_FILES['mainScope'] = $mainScope; } - $this->assertEquals($expected, $fileForm->extractValue($this->requestMock)); + $this->assertEquals($expected, $model->extractValue($this->requestMock)); if ($mainScope) { unset($_FILES['mainScope']); } @@ -163,7 +184,6 @@ public function extractValueWithRequestScopeDataProvider() */ public function testValidateValueNotToUpload($expected, $value, $isAjax = false, $isRequired = true) { - $fileForm = $this->getClass($value, $isAjax); $this->attributeMetadataMock->expects( $this->any() )->method( @@ -179,7 +199,13 @@ public function testValidateValueNotToUpload($expected, $value, $isAjax = false, $this->returnValue('attributeLabel') ); - $this->assertEquals($expected, $fileForm->validateValue($value)); + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => $isAjax, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertEquals($expected, $model->validateValue($value)); } public function validateValueNotToUploadDataProvider() @@ -201,8 +227,7 @@ public function validateValueNotToUploadDataProvider() public function testValidateValueToUpload($expected, $value, $parameters = []) { $parameters = array_merge(['uploaded' => true, 'valid' => true], $parameters); - $fileForm = $this->getClass($value, false); - $fileForm->expects($this->any())->method('_isUploadedFile')->will($this->returnValue($parameters['uploaded'])); + $this->attributeMetadataMock->expects($this->any())->method('isRequired')->will($this->returnValue(false)); $this->attributeMetadataMock->expects( $this->any() @@ -226,7 +251,18 @@ public function testValidateValueToUpload($expected, $value, $parameters = []) )->will( $this->returnValue($parameters['valid']) ); - $this->assertEquals($expected, $fileForm->validateValue($value)); + + $this->fileProcessorMock->expects($this->any()) + ->method('isExist') + ->willReturn($parameters['uploaded']); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertEquals($expected, $model->validateValue($value)); } public function validateValueToUploadDataProvider() @@ -248,30 +284,54 @@ public function validateValueToUploadDataProvider() public function testCompactValueIsAjax() { - $fileForm = $this->getClass('value', true); - $this->assertSame($fileForm, $fileForm->compactValue('aValue')); + $model = $this->initialize([ + 'value' => 'value', + 'isAjax' => true, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertSame($model, $model->compactValue('aValue')); } public function testCompactValueNoDelete() { - $fileForm = $this->getClass('value', false); $this->attributeMetadataMock->expects($this->any())->method('isRequired')->will($this->returnValue(false)); - $this->assertSame('value', $fileForm->compactValue([])); + + $model = $this->initialize([ + 'value' => 'value', + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->fileProcessorMock->expects($this->once()) + ->method('removeUploadedFile') + ->with('value') + ->willReturnSelf(); + + $this->assertSame([], $model->compactValue([])); } public function testCompactValueDelete() { - $fileForm = $this->getClass('value', false); $this->attributeMetadataMock->expects($this->any())->method('isRequired')->will($this->returnValue(false)); + $mediaDirMock = $this->getMockForAbstractClass('\Magento\Framework\Filesystem\Directory\WriteInterface'); $mediaDirMock->expects($this->once()) ->method('delete') - ->with(self::ENTITY_TYPE . 'value'); + ->with(self::ENTITY_TYPE . '/' . 'value'); + $this->fileSystemMock->expects($this->once()) ->method('getDirectoryWrite') - ->with(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA) + ->with(DirectoryList::MEDIA) ->will($this->returnValue($mediaDirMock)); - $this->assertSame('', $fileForm->compactValue(['delete' => true])); + + $model = $this->initialize([ + 'value' => 'value', + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertSame('', $model->compactValue(['delete' => true])); } public function testCompactValueTmpFile() @@ -279,11 +339,10 @@ public function testCompactValueTmpFile() $value = ['tmp_name' => 'tmp.file', 'name' => 'new.file']; $expected = 'saved.file'; - $fileForm = $this->getClass(null, false); $mediaDirMock = $this->getMockForAbstractClass('\Magento\Framework\Filesystem\Directory\WriteInterface'); $this->fileSystemMock->expects($this->once()) ->method('getDirectoryWrite') - ->with(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA) + ->with(DirectoryList::MEDIA) ->will($this->returnValue($mediaDirMock)); $mediaDirMock->expects($this->any()) ->method('getAbsolutePath') @@ -309,14 +368,26 @@ public function testCompactValueTmpFile() ->method('getUploadedFileName') ->will($this->returnValue($expected)); - $this->assertSame($expected, $fileForm->compactValue($value)); + $model = $this->initialize([ + 'value' => null, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertSame($expected, $model->compactValue($value)); } public function testRestoreValue() { $value = 'value'; - $fileForm = $this->getClass($value, false); - $this->assertEquals($value, $fileForm->restoreValue('aValue')); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertEquals($value, $model->restoreValue('aValue')); } /** @@ -325,8 +396,13 @@ public function testRestoreValue() */ public function testOutputValueNonJson($format) { - $fileForm = $this->getClass('value', false); - $this->assertSame('', $fileForm->outputValue($format)); + $model = $this->initialize([ + 'value' => 'value', + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertSame('', $model->outputValue($format)); } public function outputValueDataProvider() @@ -344,7 +420,7 @@ public function testOutputValueJson() { $value = 'value'; $urlKey = 'url_key'; - $fileForm = $this->getClass($value, false); + $this->urlEncode->expects( $this->once() )->method( @@ -354,36 +430,229 @@ public function testOutputValueJson() )->will( $this->returnValue($urlKey) ); + $expected = ['value' => $value, 'url_key' => $urlKey]; - $this->assertSame($expected, $fileForm->outputValue(ElementFactory::OUTPUT_FORMAT_JSON)); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertSame($expected, $model->outputValue(ElementFactory::OUTPUT_FORMAT_JSON)); } /** - * Helper for creating the unit under test. - * - * @param string|int|bool|null $value The value undergoing testing by a given test - * @param bool $isAjax - * @return \PHPUnit_Framework_MockObject_MockObject | File + * @param array $data + * @return \Magento\Customer\Model\Metadata\Form\File */ - protected function getClass($value, $isAjax) + private function initialize(array $data) { - $fileForm = $this->getMock( - 'Magento\Customer\Model\Metadata\Form\File', - ['_isUploadedFile'], - [ - $this->localeMock, - $this->loggerMock, - $this->attributeMetadataMock, - $this->localeResolverMock, - $value, - self::ENTITY_TYPE, - $isAjax, - $this->urlEncode, - $this->fileValidatorMock, - $this->fileSystemMock, - $this->uploaderFactoryMock - ] + $model = new \Magento\Customer\Model\Metadata\Form\File( + $this->localeMock, + $this->loggerMock, + $this->attributeMetadataMock, + $this->localeResolverMock, + $data['value'], + $data['entityTypeCode'], + $data['isAjax'], + $this->urlEncode, + $this->fileValidatorMock, + $this->fileSystemMock, + $this->uploaderFactoryMock + ); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $objectManager->setBackwardCompatibleProperty( + $model, + 'fileProcessor', + $this->fileProcessorMock ); - return $fileForm; + + return $model; + } + + public function testExtractValueFileUploaderUIComponent() + { + $attributeCode = 'img1'; + $requestScope = 'customer'; + $fileName = 'filename.ext1'; + + $this->attributeMetadataMock->expects($this->exactly(2)) + ->method('getAttributeCode') + ->willReturn($attributeCode); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with($requestScope) + ->willReturn([ + $attributeCode => [ + [ + 'file' => $fileName, + ], + ], + ]); + + $model = $this->initialize([ + 'value' => 'value', + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $model->setRequestScope($requestScope); + $result = $model->extractValue($this->requestMock); + + $this->assertEquals(['file' => $fileName], $result); + } + + public function testCompactValueRemoveUiComponentValue() + { + $value = 'value'; + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->fileProcessorMock->expects($this->once()) + ->method('removeUploadedFile') + ->with($value) + ->willReturnSelf(); + + $this->assertEquals([], $model->compactValue([])); + } + + public function testCompactValueNoAction() + { + $value = 'value'; + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertEquals($value, $model->compactValue($value)); + } + + public function testCompactValueUiComponent() + { + $value = [ + 'file' => 'filename', + ]; + + $model = $this->initialize([ + 'value' => null, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->fileProcessorMock->expects($this->once()) + ->method('moveTemporaryFile') + ->with($value['file']) + ->willReturn(true); + + $this->assertTrue($model->compactValue($value)); + } + + public function testCompactValueInputField() + { + $value = [ + 'name' => 'filename.ext1', + 'tmp_name' => 'tmpfilename.ext1', + ]; + + $absolutePath = 'absolute_path'; + $uploadedFilename = 'filename.ext1'; + + $mediaDirectoryMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\WriteInterface') + ->getMockForAbstractClass(); + $mediaDirectoryMock->expects($this->once()) + ->method('getAbsolutePath') + ->with(self::ENTITY_TYPE) + ->willReturn($absolutePath); + + $this->fileSystemMock->expects($this->once()) + ->method('getDirectoryWrite') + ->with(DirectoryList::MEDIA) + ->willReturn($mediaDirectoryMock); + + $uploaderMock = $this->getMockBuilder('Magento\Framework\File\Uploader') + ->disableOriginalConstructor() + ->getMock(); + $uploaderMock->expects($this->once()) + ->method('setFilesDispersion') + ->with(true) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setFilenamesCaseSensitivity') + ->with(false) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('setAllowRenameFiles') + ->with(true) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('save') + ->with($absolutePath, $value['name']) + ->willReturnSelf(); + $uploaderMock->expects($this->once()) + ->method('getUploadedFileName') + ->willReturn($uploadedFilename); + + $this->uploaderFactoryMock->expects($this->once()) + ->method('create') + ->with(['fileId' => $value]) + ->willReturn($uploaderMock); + + $model = $this->initialize([ + 'value' => null, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertEquals($uploadedFilename, $model->compactValue($value)); + } + + public function testCompactValueInputFieldWithException() + { + $value = [ + 'name' => 'filename.ext1', + 'tmp_name' => 'tmpfilename.ext1', + ]; + + $originValue = 'origin'; + + $mediaDirectoryMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\WriteInterface') + ->getMockForAbstractClass(); + $mediaDirectoryMock->expects($this->once()) + ->method('delete') + ->with(self::ENTITY_TYPE . '/' . $originValue); + + $this->fileSystemMock->expects($this->once()) + ->method('getDirectoryWrite') + ->with(DirectoryList::MEDIA) + ->willReturn($mediaDirectoryMock); + + $exception = new \Exception('Error'); + + $this->uploaderFactoryMock->expects($this->once()) + ->method('create') + ->with(['fileId' => $value]) + ->willThrowException($exception); + + $this->loggerMock->expects($this->once()) + ->method('critical') + ->with($exception) + ->willReturnSelf(); + + $model = $this->initialize([ + 'value' => $originValue, + 'isAjax' => false, + 'entityTypeCode' => self::ENTITY_TYPE, + ]); + + $this->assertEquals('', $model->compactValue($value)); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/HiddenTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/HiddenTest.php index 58bf6fbd6db59..3692904580cd6 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/HiddenTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/HiddenTest.php @@ -1,6 +1,6 @@ getMock( - 'Magento\Customer\Model\Metadata\Form\Image', - ['_isUploadedFile'], - [ - $this->localeMock, - $this->loggerMock, - $this->attributeMetadataMock, - $this->localeResolverMock, - $value, - 0, - $isAjax, - $this->urlEncode, - $this->fileValidatorMock, - $this->fileSystemMock, - $this->uploaderFactoryMock - ] + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Url\EncoderInterface + */ + protected $urlEncode; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\MediaStorage\Model\File\Validator\NotProtectedExtension + */ + protected $fileValidatorMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Filesystem + */ + protected $fileSystemMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Request\Http + */ + protected $requestMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\File\UploaderFactory + */ + protected $uploaderFactoryMock; + + /** + * @var FileProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + private $fileProcessorMock; + + /** + * @var \Magento\Framework\Api\Data\ImageContentInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $imageContentFactory; + + protected function setUp() + { + parent::setUp(); + + $this->urlEncode = $this->getMockBuilder('Magento\Framework\Url\EncoderInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->fileValidatorMock = $this->getMockBuilder( + 'Magento\MediaStorage\Model\File\Validator\NotProtectedExtension' + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->fileSystemMock = $this->getMockBuilder('Magento\Framework\Filesystem') + ->disableOriginalConstructor() + ->getMock(); + + $this->requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http') + ->disableOriginalConstructor() + ->getMock(); + + $this->uploaderFactoryMock = $this->getMockBuilder('Magento\Framework\File\UploaderFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->fileProcessorMock = $this->getMockBuilder('Magento\Customer\Model\FileProcessor') + ->disableOriginalConstructor() + ->getMock(); + + $this->imageContentFactory = $this->getMockBuilder('Magento\Framework\Api\Data\ImageContentInterfaceFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + } + + /** + * @param array $data + * @return \Magento\Customer\Model\Metadata\Form\File + */ + private function initialize(array $data) + { + $model = new \Magento\Customer\Model\Metadata\Form\Image( + $this->localeMock, + $this->loggerMock, + $this->attributeMetadataMock, + $this->localeResolverMock, + $data['value'], + $data['entityTypeCode'], + $data['isAjax'], + $this->urlEncode, + $this->fileValidatorMock, + $this->fileSystemMock, + $this->uploaderFactoryMock + ); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $objectManager->setBackwardCompatibleProperty( + $model, + 'fileProcessor', + $this->fileProcessorMock + ); + $objectManager->setBackwardCompatibleProperty( + $model, + 'imageContentFactory', + $this->imageContentFactory ); - return $imageForm; + + return $model; + } + + public function testValidateIsNotValidFile() + { + $value = [ + 'tmp_name' => 'tmp_file', + 'name' => 'realFileName', + ]; + + $this->attributeMetadataMock->expects($this->once()) + ->method('getStoreLabel') + ->willReturn('File Input Field Label'); + + $this->fileProcessorMock->expects($this->once()) + ->method('isExist') + ->with(FileProcessor::TMP_DIR . '/' . $value['tmp_name']) + ->willReturn(true); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertEquals(['"realFileName" is not a valid file.'], $model->validateValue($value)); + } + + public function testValidate() + { + $value = [ + 'tmp_name' => __DIR__ . '/_files/logo.gif', + 'name' => 'logo.gif', + ]; + + $this->attributeMetadataMock->expects($this->once()) + ->method('getStoreLabel') + ->willReturn('File Input Field Label'); + + $this->fileProcessorMock->expects($this->once()) + ->method('isExist') + ->with(FileProcessor::TMP_DIR . '/' . $value['name']) + ->willReturn(true); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertTrue($model->validateValue($value)); } - public function validateValueToUploadDataProvider() + public function testValidateMaxFileSize() { - $imagePath = __DIR__ . '/_files/logo.gif'; - return [ - [ - ['"realFileName" is not a valid file.'], - ['tmp_name' => 'tmp_file', 'name' => 'realFileName'], - ['valid' => false], - ], - [true, ['tmp_name' => $imagePath, 'name' => 'logo.gif']] + $value = [ + 'tmp_name' => __DIR__ . '/_files/logo.gif', + 'name' => 'logo.gif', + 'size' => 2, ]; + + $maxFileSize = 1; + + $validationRuleMock = $this->getMockBuilder('Magento\Customer\Api\Data\ValidationRuleInterface') + ->getMockForAbstractClass(); + $validationRuleMock->expects($this->any()) + ->method('getName') + ->willReturn('max_file_size'); + $validationRuleMock->expects($this->any()) + ->method('getValue') + ->willReturn($maxFileSize); + + $this->attributeMetadataMock->expects($this->once()) + ->method('getStoreLabel') + ->willReturn('File Input Field Label'); + $this->attributeMetadataMock->expects($this->once()) + ->method('getValidationRules') + ->willReturn([$validationRuleMock]); + + $this->fileProcessorMock->expects($this->once()) + ->method('isExist') + ->with(FileProcessor::TMP_DIR . '/' . $value['name']) + ->willReturn(true); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertEquals(['"logo.gif" exceeds the allowed file size.'], $model->validateValue($value)); + } + + public function testValidateMaxImageWidth() + { + $value = [ + 'tmp_name' => __DIR__ . '/_files/logo.gif', + 'name' => 'logo.gif', + ]; + + $maxImageWidth = 1; + + $validationRuleMock = $this->getMockBuilder('Magento\Customer\Api\Data\ValidationRuleInterface') + ->getMockForAbstractClass(); + $validationRuleMock->expects($this->any()) + ->method('getName') + ->willReturn('max_image_width'); + $validationRuleMock->expects($this->any()) + ->method('getValue') + ->willReturn($maxImageWidth); + + $this->attributeMetadataMock->expects($this->once()) + ->method('getStoreLabel') + ->willReturn('File Input Field Label'); + $this->attributeMetadataMock->expects($this->once()) + ->method('getValidationRules') + ->willReturn([$validationRuleMock]); + + $this->fileProcessorMock->expects($this->once()) + ->method('isExist') + ->with(FileProcessor::TMP_DIR . '/' . $value['name']) + ->willReturn(true); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertEquals(['"logo.gif" width exceeds allowed value of 1 px.'], $model->validateValue($value)); + } + + public function testValidateMaxImageHeight() + { + $value = [ + 'tmp_name' => __DIR__ . '/_files/logo.gif', + 'name' => 'logo.gif', + ]; + + $maxImageHeight = 1; + + $validationRuleMock = $this->getMockBuilder('Magento\Customer\Api\Data\ValidationRuleInterface') + ->getMockForAbstractClass(); + $validationRuleMock->expects($this->any()) + ->method('getName') + ->willReturn('max_image_heght'); + $validationRuleMock->expects($this->any()) + ->method('getValue') + ->willReturn($maxImageHeight); + + $this->attributeMetadataMock->expects($this->once()) + ->method('getStoreLabel') + ->willReturn('File Input Field Label'); + $this->attributeMetadataMock->expects($this->once()) + ->method('getValidationRules') + ->willReturn([$validationRuleMock]); + + $this->fileProcessorMock->expects($this->once()) + ->method('isExist') + ->with(FileProcessor::TMP_DIR . '/' . $value['name']) + ->willReturn(true); + + $model = $this->initialize([ + 'value' => $value, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertEquals(['"logo.gif" height exceeds allowed value of 1 px.'], $model->validateValue($value)); + } + + public function testCompactValueNoChanges() + { + $originValue = 'filename.ext1'; + + $value = [ + 'file' => $originValue, + ]; + + $model = $this->initialize([ + 'value' => $originValue, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertEquals($originValue, $model->compactValue($value)); + } + + public function testCompactValueUiComponentAddress() + { + $originValue = 'filename.ext1'; + + $value = [ + 'file' => 'filename.ext2', + ]; + + $this->fileProcessorMock->expects($this->once()) + ->method('moveTemporaryFile') + ->with($value['file']) + ->willReturn(true); + + $model = $this->initialize([ + 'value' => $originValue, + 'isAjax' => false, + 'entityTypeCode' => AddressMetadataInterface::ENTITY_TYPE_ADDRESS, + ]); + + $this->assertTrue($model->compactValue($value)); + } + + public function testCompactValueUiComponentCustomer() + { + $originValue = 'filename.ext1'; + + $value = [ + 'file' => 'filename.ext2', + 'name' => 'filename.ext2', + 'type' => 'image', + ]; + + $base64EncodedData = 'encoded_data'; + + $this->fileProcessorMock->expects($this->once()) + ->method('isExist') + ->with(FileProcessor::TMP_DIR . '/' . $value['file']) + ->willReturn(true); + $this->fileProcessorMock->expects($this->once()) + ->method('getBase64EncodedData') + ->with(FileProcessor::TMP_DIR . '/' . $value['file']) + ->willReturn($base64EncodedData); + $this->fileProcessorMock->expects($this->once()) + ->method('removeUploadedFile') + ->with(FileProcessor::TMP_DIR . '/' . $value['file']) + ->willReturnSelf(); + + $imageContentMock = $this->getMockBuilder('Magento\Framework\Api\Data\ImageContentInterface') + ->getMockForAbstractClass(); + $imageContentMock->expects($this->once()) + ->method('setName') + ->with($value['name']) + ->willReturnSelf(); + $imageContentMock->expects($this->once()) + ->method('setBase64EncodedData') + ->with($base64EncodedData) + ->willReturnSelf(); + $imageContentMock->expects($this->once()) + ->method('setType') + ->with($value['type']) + ->willReturnSelf(); + + $this->imageContentFactory->expects($this->once()) + ->method('create') + ->willReturn($imageContentMock); + + $model = $this->initialize([ + 'value' => $originValue, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertEquals($imageContentMock, $model->compactValue($value)); + } + + public function testCompactValueUiComponentCustomerNotExists() + { + $originValue = 'filename.ext1'; + + $value = [ + 'file' => 'filename.ext2', + 'name' => 'filename.ext2', + 'type' => 'image', + ]; + + $this->fileProcessorMock->expects($this->once()) + ->method('isExist') + ->with(FileProcessor::TMP_DIR . '/' . $value['file']) + ->willReturn(false); + + $model = $this->initialize([ + 'value' => $originValue, + 'isAjax' => false, + 'entityTypeCode' => CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, + ]); + + $this->assertEquals($originValue, $model->compactValue($value)); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/MultilineTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/MultilineTest.php index 5922cc251a219..1e0f844cef024 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/MultilineTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/MultilineTest.php @@ -1,6 +1,6 @@ shareConfig = $this->getMockBuilder(Share::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager = $this->getMock(StoreManagerInterface::class); + + $this->plugin = new AllowedCountries($this->shareConfig, $this->storeManager); + } + + public function testGetAllowedCountriesWithGlobalScope() + { + $expectedFilter = 1; + $expectedScope = ScopeInterface::SCOPE_WEBSITES; + + $this->shareConfig->expects($this->once()) + ->method('isGlobalScope') + ->willReturn(true); + $originalAllowedCountriesMock = $this->getMockBuilder(\Magento\Directory\Model\AllowedCountries::class) + ->disableOriginalConstructor() + ->getMock(); + $websiteMock = $this->getMock(WebsiteInterface::class); + $websiteMock->expects($this->once()) + ->method('getId') + ->willReturn($expectedFilter); + $this->storeManager->expects($this->once()) + ->method('getWebsites') + ->willReturn([$websiteMock]); + + $this->assertEquals( + [$expectedScope, [$expectedFilter]], + $this->plugin->beforeGetAllowedCountries($originalAllowedCountriesMock) + ); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php b/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php index bd0600899edcb..6fe369391a343 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php @@ -1,6 +1,6 @@ countriesFactoryMock = + $this->getMockBuilder(\Magento\Directory\Model\ResourceModel\Country\CollectionFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->allowedCountriesMock = $this->getMockBuilder(AllowedCountries::class) + ->disableOriginalConstructor() + ->getMock(); + $eavCollectionFactoryMock = + $this->getMockBuilder(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $optionsFactoryMock = + $this->getMockBuilder(\Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManagerMock = $this->getMock(StoreManagerInterface::class); + $this->shareConfigMock = $this->getMockBuilder(Share::class) + ->disableOriginalConstructor() + ->getMock(); + $this->countryByWebsite = new CountryWithWebsites( + $eavCollectionFactoryMock, + $optionsFactoryMock, + $this->countriesFactoryMock, + $this->allowedCountriesMock, + $this->storeManagerMock, + $this->shareConfigMock + ); + } + + public function testGetAllOptions() + { + $website1 = $this->getMock(WebsiteInterface::class); + $website2 = $this->getMock(WebsiteInterface::class); + + $website1->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn(1); + $website2->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn(2); + $this->storeManagerMock->expects($this->once()) + ->method('getWebsites') + ->willReturn([$website1, $website2]); + $collectionMock = $this->getMockBuilder(AbstractDb::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->allowedCountriesMock->expects($this->exactly(2)) + ->method('getAllowedCountries') + ->withConsecutive( + ['website', 1], + ['website', 2] + ) + ->willReturnMap([ + ['website', 1, ['AM' => 'AM']], + ['website', 2, ['AM' => 'AM', 'DZ' => 'DZ']] + ]); + $this->countriesFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($collectionMock); + $collectionMock->expects($this->once()) + ->method('addFieldToFilter') + ->with('country_id', ['in' => ['AM' => 'AM', 'DZ' => 'DZ']]) + ->willReturnSelf(); + $collectionMock->expects($this->once()) + ->method('toOptionArray') + ->willReturn([ + ['value' => 'AM', 'label' => 'UZ'] + ]); + + $this->assertEquals([ + ['value' => 'AM', 'label' => 'UZ', 'website_ids' => [1, 2]] + ], $this->countryByWebsite->getAllOptions()); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Address/RelationTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Address/RelationTest.php index 6a2c7ac2c32af..8827161d94808 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Address/RelationTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Address/RelationTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/etc/address_formats.xml b/app/code/Magento/Customer/etc/address_formats.xml index f501df2f3b63a..c4d74375c32d3 100644 --- a/app/code/Magento/Customer/etc/address_formats.xml +++ b/app/code/Magento/Customer/etc/address_formats.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/address_formats.xsd b/app/code/Magento/Customer/etc/address_formats.xsd index f5df16ffcc5ea..14d0ad4598054 100644 --- a/app/code/Magento/Customer/etc/address_formats.xsd +++ b/app/code/Magento/Customer/etc/address_formats.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/adminhtml/di.xml b/app/code/Magento/Customer/etc/adminhtml/di.xml index 08c9cb95efe66..cf2254307a9ed 100644 --- a/app/code/Magento/Customer/etc/adminhtml/di.xml +++ b/app/code/Magento/Customer/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/adminhtml/menu.xml b/app/code/Magento/Customer/etc/adminhtml/menu.xml index 31765fa89e8fe..eaa65dc280b00 100644 --- a/app/code/Magento/Customer/etc/adminhtml/menu.xml +++ b/app/code/Magento/Customer/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/adminhtml/routes.xml b/app/code/Magento/Customer/etc/adminhtml/routes.xml index 9f3b07f486025..4c68008dd1437 100644 --- a/app/code/Magento/Customer/etc/adminhtml/routes.xml +++ b/app/code/Magento/Customer/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Customer/etc/adminhtml/system.xml b/app/code/Magento/Customer/etc/adminhtml/system.xml index 78e11418bcf11..d96ff1b0694ee 100644 --- a/app/code/Magento/Customer/etc/adminhtml/system.xml +++ b/app/code/Magento/Customer/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ @@ -176,6 +176,19 @@ required-entry validate-digits + + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + + diff --git a/app/code/Magento/Customer/etc/cache.xml b/app/code/Magento/Customer/etc/cache.xml index 37d1a63f69a4e..553f1f6535d52 100644 --- a/app/code/Magento/Customer/etc/cache.xml +++ b/app/code/Magento/Customer/etc/cache.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/config.xml b/app/code/Magento/Customer/etc/config.xml index effe94adad747..f891cd284e086 100644 --- a/app/code/Magento/Customer/etc/config.xml +++ b/app/code/Magento/Customer/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/crontab.xml b/app/code/Magento/Customer/etc/crontab.xml index 472a49feb39fc..eda64cf2eca93 100644 --- a/app/code/Magento/Customer/etc/crontab.xml +++ b/app/code/Magento/Customer/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml index bb6577470ba54..bd9d9e88e754b 100644 --- a/app/code/Magento/Customer/etc/di.xml +++ b/app/code/Magento/Customer/etc/di.xml @@ -1,7 +1,7 @@ @@ -304,6 +304,9 @@ + + + diff --git a/app/code/Magento/Customer/etc/email_templates.xml b/app/code/Magento/Customer/etc/email_templates.xml index 0d6b4d5877088..23fa73056b4c2 100644 --- a/app/code/Magento/Customer/etc/email_templates.xml +++ b/app/code/Magento/Customer/etc/email_templates.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/events.xml b/app/code/Magento/Customer/etc/events.xml index 45caa32d680c6..0e65ddca44924 100644 --- a/app/code/Magento/Customer/etc/events.xml +++ b/app/code/Magento/Customer/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/fieldset.xml b/app/code/Magento/Customer/etc/fieldset.xml index a43df71873475..b219305e3b9fa 100644 --- a/app/code/Magento/Customer/etc/fieldset.xml +++ b/app/code/Magento/Customer/etc/fieldset.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/frontend/di.xml b/app/code/Magento/Customer/etc/frontend/di.xml index 91c6531a21e4f..4562acb00fe5b 100644 --- a/app/code/Magento/Customer/etc/frontend/di.xml +++ b/app/code/Magento/Customer/etc/frontend/di.xml @@ -1,7 +1,7 @@ @@ -60,4 +60,14 @@ + + + + + Magento\Customer\Model\Authorization\CustomerSessionUserContext + 10 + + + + diff --git a/app/code/Magento/Customer/etc/frontend/events.xml b/app/code/Magento/Customer/etc/frontend/events.xml index 5bb0ffe3cb7c2..75cc5f7c929dc 100644 --- a/app/code/Magento/Customer/etc/frontend/events.xml +++ b/app/code/Magento/Customer/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/frontend/page_types.xml b/app/code/Magento/Customer/etc/frontend/page_types.xml index bfcda34cc3111..77a0fb520bbd3 100644 --- a/app/code/Magento/Customer/etc/frontend/page_types.xml +++ b/app/code/Magento/Customer/etc/frontend/page_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/frontend/routes.xml b/app/code/Magento/Customer/etc/frontend/routes.xml index d448185245add..eb91d26288ab4 100644 --- a/app/code/Magento/Customer/etc/frontend/routes.xml +++ b/app/code/Magento/Customer/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Customer/etc/frontend/sections.xml b/app/code/Magento/Customer/etc/frontend/sections.xml index 83d6394cd0951..877be8e0266ee 100644 --- a/app/code/Magento/Customer/etc/frontend/sections.xml +++ b/app/code/Magento/Customer/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/indexer.xml b/app/code/Magento/Customer/etc/indexer.xml index b48592cafbb20..0d3c8cb5b9bc2 100644 --- a/app/code/Magento/Customer/etc/indexer.xml +++ b/app/code/Magento/Customer/etc/indexer.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/module.xml b/app/code/Magento/Customer/etc/module.xml index a4bc17a1e2cfd..d513fb67bc660 100644 --- a/app/code/Magento/Customer/etc/module.xml +++ b/app/code/Magento/Customer/etc/module.xml @@ -1,12 +1,12 @@ - + diff --git a/app/code/Magento/Customer/etc/mview.xml b/app/code/Magento/Customer/etc/mview.xml index 4f88d94f15ede..ebeaac0114158 100644 --- a/app/code/Magento/Customer/etc/mview.xml +++ b/app/code/Magento/Customer/etc/mview.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/sections.xsd b/app/code/Magento/Customer/etc/sections.xsd index 91a09129357bb..f2be0302db725 100644 --- a/app/code/Magento/Customer/etc/sections.xsd +++ b/app/code/Magento/Customer/etc/sections.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/validation.xml b/app/code/Magento/Customer/etc/validation.xml index b496a9345cb82..d06164942c7d4 100644 --- a/app/code/Magento/Customer/etc/validation.xml +++ b/app/code/Magento/Customer/etc/validation.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/webapi.xml b/app/code/Magento/Customer/etc/webapi.xml index 3a492e7370242..f78d9c01d16a3 100644 --- a/app/code/Magento/Customer/etc/webapi.xml +++ b/app/code/Magento/Customer/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/webapi_rest/di.xml b/app/code/Magento/Customer/etc/webapi_rest/di.xml index 045f16cc6d028..a9d21aea930d3 100644 --- a/app/code/Magento/Customer/etc/webapi_rest/di.xml +++ b/app/code/Magento/Customer/etc/webapi_rest/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/etc/webapi_soap/di.xml b/app/code/Magento/Customer/etc/webapi_soap/di.xml index ae882cfacba68..61cdd928de4f4 100644 --- a/app/code/Magento/Customer/etc/webapi_soap/di.xml +++ b/app/code/Magento/Customer/etc/webapi_soap/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/registration.php b/app/code/Magento/Customer/registration.php index a1f0064643132..4c1e81d195b19 100644 --- a/app/code/Magento/Customer/registration.php +++ b/app/code/Magento/Customer/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_cart.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_cart.xml index 965dc8fa4d3ad..1cb5d82323760 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_cart.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_cart.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_carts.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_carts.xml index c5ffdc4fbae7e..3fa611ebd6e88 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_carts.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_carts.xml @@ -1,7 +1,7 @@ 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 7d13c2dcf9a02..dfa8379891ad2 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 @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml index 2bf05d10369f5..c6f3c3e2ead71 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_newsletter.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_newsletter.xml index 103b5ac2b38c4..10b4a31f5d963 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_newsletter.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_newsletter.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_orders.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_orders.xml index 031ae90eeab4c..e99d0a053eb0d 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_orders.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_orders.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_productreviews.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_productreviews.xml index 5b074b5095fef..671ef7ec0e7cc 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_productreviews.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_productreviews.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewcart.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewcart.xml index b44f04157ebe0..cc5d9e0da8225 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewcart.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewcart.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewwishlist.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewwishlist.xml index bad08a8f09737..8cd4ec724e3e3 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewwishlist.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_viewwishlist.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_online_index.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_online_index.xml index fb34ba65f7e26..1ae4259bc75fe 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_online_index.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_online_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/adminhtml/requirejs-config.js b/app/code/Magento/Customer/view/adminhtml/requirejs-config.js index 666193865f20a..589ece5b14104 100644 --- a/app/code/Magento/Customer/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/Customer/view/adminhtml/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -14,4 +14,4 @@ var config = { observableInputs: 'Magento_Customer/edit/tab/js/addresses' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml b/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml index e5450890826b1..49cc0c8c7395a 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/edit/js.phtml @@ -1,6 +1,6 @@ @@ -20,6 +20,7 @@ */*/new + Magento_Customer::manage diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml index 2dc9e89090c4c..ff5291afff4e5 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ customer_online_grid.customer_online_grid_data_source customer_online_columns + Magento_Customer::online diff --git a/app/code/Magento/Customer/view/adminhtml/web/edit/post-wrapper.js b/app/code/Magento/Customer/view/adminhtml/web/edit/post-wrapper.js index d6fc60b5fb932..9b368adcbe665 100644 --- a/app/code/Magento/Customer/view/adminhtml/web/edit/post-wrapper.js +++ b/app/code/Magento/Customer/view/adminhtml/web/edit/post-wrapper.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Customer/view/adminhtml/web/edit/tab/js/addresses.js b/app/code/Magento/Customer/view/adminhtml/web/edit/tab/js/addresses.js index a3e04fc43fc40..7242dc945178d 100644 --- a/app/code/Magento/Customer/view/adminhtml/web/edit/tab/js/addresses.js +++ b/app/code/Magento/Customer/view/adminhtml/web/edit/tab/js/addresses.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -563,4 +563,4 @@ define([ observableInputs: $.mage.observableInputs, dataItemDeleteButton: $.mage.dataItemDeleteButton }; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Customer/view/adminhtml/web/js/bootstrap/customer-post-action.js b/app/code/Magento/Customer/view/adminhtml/web/js/bootstrap/customer-post-action.js index 7ea9247ecd94b..661c4e3d471c3 100644 --- a/app/code/Magento/Customer/view/adminhtml/web/js/bootstrap/customer-post-action.js +++ b/app/code/Magento/Customer/view/adminhtml/web/js/bootstrap/customer-post-action.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 index 6ede18b0edf35..cd4e554ec01f6 100644 --- a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml +++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml @@ -1,7 +1,7 @@ @@ -98,10 +98,14 @@ number select + Magento_Ui/js/form/element/website customer true + + ${ $.provider }:data.customer.entity_id + http://docs.magento.com/m2/ce/user_guide/configuration/scope.html If your Magento site has multiple views, you can set the scope to apply to a specific view. @@ -256,6 +260,10 @@ Send Welcome Email From number select + customer + + ${ $.provider }:data.customer.store_id + @@ -370,9 +378,13 @@ text select address + Magento_Ui/js/form/element/country true + + ${ $.provider }:data.customer.website_id + diff --git a/app/code/Magento/Customer/view/frontend/email/account_new.html b/app/code/Magento/Customer/view/frontend/email/account_new.html index 9d67e26e8e715..dac8e1ce57505 100644 --- a/app/code/Magento/Customer/view/frontend/email/account_new.html +++ b/app/code/Magento/Customer/view/frontend/email/account_new.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/account_new_confirmation.html b/app/code/Magento/Customer/view/frontend/email/account_new_confirmation.html index 193a1faed662d..5432956e8f03f 100644 --- a/app/code/Magento/Customer/view/frontend/email/account_new_confirmation.html +++ b/app/code/Magento/Customer/view/frontend/email/account_new_confirmation.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/account_new_confirmed.html b/app/code/Magento/Customer/view/frontend/email/account_new_confirmed.html index 6e94fbdcc7807..b50c944c18b46 100644 --- a/app/code/Magento/Customer/view/frontend/email/account_new_confirmed.html +++ b/app/code/Magento/Customer/view/frontend/email/account_new_confirmed.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/account_new_no_password.html b/app/code/Magento/Customer/view/frontend/email/account_new_no_password.html index 14cd8e98f8bfe..1c5371bd4868b 100644 --- a/app/code/Magento/Customer/view/frontend/email/account_new_no_password.html +++ b/app/code/Magento/Customer/view/frontend/email/account_new_no_password.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/change_email.html b/app/code/Magento/Customer/view/frontend/email/change_email.html index ab24368c02239..09d1537e1cc07 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html index d2ca4d4cae0a2..23280b2822b48 100644 --- a/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html +++ b/app/code/Magento/Customer/view/frontend/email/change_email_and_password.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/password_new.html b/app/code/Magento/Customer/view/frontend/email/password_new.html index 12c5a30ddf103..f5c2d87128300 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_new.html +++ b/app/code/Magento/Customer/view/frontend/email/password_new.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset.html b/app/code/Magento/Customer/view/frontend/email/password_reset.html index 061e640810705..a255e2f99e575 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_reset.html +++ b/app/code/Magento/Customer/view/frontend/email/password_reset.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html index a07b36c148005..efdd89bbec720 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html +++ b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account.xml index a96dfcd86e542..4024331be0cbc 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_confirmation.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_confirmation.xml index 5bf52253badd7..c2d7dc01dbbea 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_confirmation.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_confirmation.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml index 8eaba5c75fe1d..8a42132dd01fd 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_create.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_createpassword.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_createpassword.xml index 298ad6e9c3968..878fd56999045 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_createpassword.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_createpassword.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_edit.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_edit.xml index aa09fecc68170..452d98821105f 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_edit.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_forgotpassword.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_forgotpassword.xml index e33da515e150a..a39f15c201c65 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_forgotpassword.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_forgotpassword.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_index.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_index.xml index 5d1da28d4c189..e3fb14923ff5e 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_index.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_login.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_login.xml index 32b471dff8b33..e7c157acb1bfb 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_login.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_login.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_account_logoutsuccess.xml b/app/code/Magento/Customer/view/frontend/layout/customer_account_logoutsuccess.xml index 93b522c90dc60..d76363eaffb05 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_account_logoutsuccess.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_account_logoutsuccess.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml b/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml index 46bea31094523..67ab9768157e5 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_address_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/customer_address_index.xml b/app/code/Magento/Customer/view/frontend/layout/customer_address_index.xml index 8706ba25c5691..42f7b5ea38a69 100644 --- a/app/code/Magento/Customer/view/frontend/layout/customer_address_index.xml +++ b/app/code/Magento/Customer/view/frontend/layout/customer_address_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/layout/default.xml b/app/code/Magento/Customer/view/frontend/layout/default.xml index 50580f73a9d31..2c2ae1a5c4993 100644 --- a/app/code/Magento/Customer/view/frontend/layout/default.xml +++ b/app/code/Magento/Customer/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Customer/view/frontend/requirejs-config.js b/app/code/Magento/Customer/view/frontend/requirejs-config.js index 53f12373bfd92..4ff5a81cc5d92 100644 --- a/app/code/Magento/Customer/view/frontend/requirejs-config.js +++ b/app/code/Magento/Customer/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml b/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml index 83d4bad447268..02d877648f0d8 100644 --- a/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/account/authentication-popup.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml b/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml index d107ebdb18811..0bdef626b3df7 100644 --- a/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/newcustomer.phtml @@ -1,6 +1,6 @@ showMiddlename(); $suffix = $block->showSuffix(); ?> -getNoWrap()): ?> +getNoWrap()): ?>
- getNoWrap()): ?> + getNoWrap()): ?> diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml index f9fadb3a4c206..23cf8af51998b 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/taxvat.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index/ExportCsv.php b/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index/ExportCsv.php index b54be91ad1788..81a310be67965 100644 --- a/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index/ExportCsv.php +++ b/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index/ExportCsv.php @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/CustomerImportExport/etc/config.xml b/app/code/Magento/CustomerImportExport/etc/config.xml index 4e520d21a7e75..8240c00223600 100644 --- a/app/code/Magento/CustomerImportExport/etc/config.xml +++ b/app/code/Magento/CustomerImportExport/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CustomerImportExport/etc/export.xml b/app/code/Magento/CustomerImportExport/etc/export.xml index 933f4e99c528d..cf226c50ef681 100644 --- a/app/code/Magento/CustomerImportExport/etc/export.xml +++ b/app/code/Magento/CustomerImportExport/etc/export.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CustomerImportExport/etc/import.xml b/app/code/Magento/CustomerImportExport/etc/import.xml index cc6715f9995f9..316947ffaf028 100644 --- a/app/code/Magento/CustomerImportExport/etc/import.xml +++ b/app/code/Magento/CustomerImportExport/etc/import.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CustomerImportExport/etc/module.xml b/app/code/Magento/CustomerImportExport/etc/module.xml index f38e2ad009643..a2bb69023d2f5 100644 --- a/app/code/Magento/CustomerImportExport/etc/module.xml +++ b/app/code/Magento/CustomerImportExport/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CustomerImportExport/registration.php b/app/code/Magento/CustomerImportExport/registration.php index cbcf924475865..9aac304811a85 100644 --- a/app/code/Magento/CustomerImportExport/registration.php +++ b/app/code/Magento/CustomerImportExport/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml index 63f0f5b51c45e..581c23c802683 100644 --- a/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml +++ b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml index 513a2d02ff48a..39f50e92aeafc 100644 --- a/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml +++ b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Deploy/Console/Command/App/ApplicationDumpCommand.php b/app/code/Magento/Deploy/Console/Command/App/ApplicationDumpCommand.php new file mode 100644 index 0000000000000..b63357be6bf8a --- /dev/null +++ b/app/code/Magento/Deploy/Console/Command/App/ApplicationDumpCommand.php @@ -0,0 +1,92 @@ +writer = $writer; + $this->sources = $sources; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('app:config:dump'); + $this->setDescription('Create dump of application'); + parent::configure(); + } + + /** + * Dump Application + * + * @param InputInterface $input + * @param OutputInterface $output + * @return boolean + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $dump = []; + $comments = []; + foreach ($this->sources as $sourceData) { + /** @var ConfigSourceInterface $source */ + $source = $sourceData['source']; + $namespace = $sourceData['namespace']; + $dump[$namespace] = $source->get(); + if (!empty($sourceData['comment'])) { + $comments[$namespace] = is_string($sourceData['comment']) + ? $sourceData['comment'] + : $sourceData['comment']->get(); + } + } + $this->writer + ->saveConfig( + [ConfigFilePool::APP_CONFIG => $dump], + true, + ConfigFilePool::LOCAL, + $comments + ); + if (!empty($comments)) { + $output->writeln($comments); + } + $output->writeln('Done.'); + return Cli::RETURN_SUCCESS; + } +} diff --git a/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php b/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php index a87fe24ec6a18..93984d5e43e8a 100644 --- a/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php +++ b/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php @@ -1,6 +1,6 @@ setDescription('Deploys static view files') ->setDefinition([ new InputOption( - self::DRY_RUN_OPTION, + Options::DRY_RUN, '-d', InputOption::VALUE_NONE, 'If specified, then no files will be actually deployed.' ), + new InputOption( + Options::NO_JAVASCRIPT, + null, + InputOption::VALUE_NONE, + 'Do not deploy JavaScript files' + ), + new InputOption( + Options::NO_CSS, + null, + InputOption::VALUE_NONE, + 'Do not deploy CSS files.' + ), + new InputOption( + Options::NO_LESS, + null, + InputOption::VALUE_NONE, + 'Do not deploy LESS files.' + ), + new InputOption( + Options::NO_IMAGES, + null, + InputOption::VALUE_NONE, + 'Do not deploy images.' + ), + new InputOption( + Options::NO_FONTS, + null, + InputOption::VALUE_NONE, + 'Do not deploy font files.' + ), + new InputOption( + Options::NO_HTML, + null, + InputOption::VALUE_NONE, + 'Do not deploy HTML files.' + ), + new InputOption( + Options::NO_MISC, + null, + InputOption::VALUE_NONE, + 'Do not deploy other types of files (.md, .jbf, .csv, etc...).' + ), + new InputOption( + Options::NO_HTML_MINIFY, + null, + InputOption::VALUE_NONE, + 'Do not minify HTML files.' + ), + new InputOption( + Options::THEME, + '-t', + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, + 'Generate static view files for only the specified themes.', + ['all'] + ), + new InputOption( + Options::EXCLUDE_THEME, + null, + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, + 'Do not generate files for the specified themes.', + ['none'] + ), + new InputOption( + Options::LANGUAGE, + '-l', + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, + 'Generate files only for the specified languages.', + ['all'] + ), + new InputOption( + Options::EXCLUDE_LANGUAGE, + null, + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, + 'Do not generate files for the specified languages.', + ['none'] + ), + new InputOption( + Options::AREA, + '-a', + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, + 'Generate files only for the specified areas.', + ['all'] + ), + new InputOption( + Options::EXCLUDE_AREA, + null, + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, + 'Do not generate files for the specified areas.', + ['none'] + ), + new InputOption( + Options::JOBS_AMOUNT, + '-j', + InputOption::VALUE_OPTIONAL, + 'Enable parallel processing using the specified number of jobs.', + self::DEFAULT_JOBS_AMOUNT + ), + new InputOption( + Options::SYMLINK_LOCALE, + null, + InputOption::VALUE_NONE, + 'Create symlinks for the files of those locales, which are passed for deployment, ' + . 'but have no customizations' + ), new InputArgument( - self::LANGUAGE_OPTION, + self::LANGUAGES_ARGUMENT, InputArgument::IS_ARRAY, - 'List of languages you want the tool populate files for.', - ['en_US'] + 'Space-separated list of ISO-636 language codes for which to output static view files.' ), ]); + parent::configure(); } /** * {@inheritdoc} + * @param $magentoAreas array + * @param $areasInclude array + * @param $areasExclude array + * @throws \InvalidArgumentException */ - protected function execute(InputInterface $input, OutputInterface $output) + private function checkAreasInput($magentoAreas, $areasInclude, $areasExclude) { - $options = $input->getOptions(); + if ($areasInclude[0] != 'all' && $areasExclude[0] != 'none') { + throw new \InvalidArgumentException( + '--area (-a) and --exclude-area cannot be used at the same time' + ); + } - $languages = $input->getArgument(self::LANGUAGE_OPTION); - foreach ($languages as $lang) { + if ($areasInclude[0] != 'all') { + foreach ($areasInclude as $area) { + if (!in_array($area, $magentoAreas)) { + throw new \InvalidArgumentException( + $area . + ' argument has invalid value, available areas are: ' . implode(', ', $magentoAreas) + ); + } + } + } - if (!$this->validator->isValid($lang)) { - throw new \InvalidArgumentException( - $lang . ' argument has invalid value, please run info:language:list for list of available locales' - ); + if ($areasExclude[0] != 'none') { + foreach ($areasExclude as $area) { + if (!in_array($area, $magentoAreas)) { + throw new \InvalidArgumentException( + $area . + ' argument has invalid value, available areas are: ' . implode(', ', $magentoAreas) + ); + } } } + } - // run the deployment logic + /** + * {@inheritdoc} + * @param $languagesInclude array + * @param $languagesExclude array + * @throws \InvalidArgumentException + */ + private function checkLanguagesInput($languagesInclude, $languagesExclude) + { + if ($languagesInclude[0] != 'all') { + foreach ($languagesInclude as $lang) { + if (!$this->validator->isValid($lang)) { + throw new \InvalidArgumentException( + $lang . + ' argument has invalid value, please run info:language:list for list of available locales' + ); + } + } + } + + if ($languagesInclude[0] != 'all' && $languagesExclude[0] != 'none') { + throw new \InvalidArgumentException( + '--language (-l) and --exclude-language cannot be used at the same time' + ); + } + } + + /** + * {@inheritdoc} + * @param $magentoThemes array + * @param $themesInclude array + * @param $themesExclude array + * @throws \InvalidArgumentException + */ + private function checkThemesInput($magentoThemes, $themesInclude, $themesExclude) + { + if ($themesInclude[0] != 'all' && $themesExclude[0] != 'none') { + throw new \InvalidArgumentException( + '--theme (-t) and --exclude-theme cannot be used at the same time' + ); + } + + if ($themesInclude[0] != 'all') { + foreach ($themesInclude as $theme) { + if (!in_array($theme, $magentoThemes)) { + throw new \InvalidArgumentException( + $theme . + ' argument has invalid value, available themes are: ' . implode(', ', $magentoThemes) + ); + } + } + } + + if ($themesExclude[0] != 'none') { + foreach ($themesExclude as $theme) { + if (!in_array($theme, $magentoThemes)) { + throw new \InvalidArgumentException( + $theme . + ' argument has invalid value, available themes are: ' . implode(', ', $magentoThemes) + ); + } + } + } + } + + /** + * {@inheritdoc} + * @param $entities array + * @param $includedEntities array + * @param $excludedEntities array + * @return array + */ + private function getDeployableEntities($entities, $includedEntities, $excludedEntities) + { + $deployableEntities = []; + if ($includedEntities[0] === 'all' && $excludedEntities[0] === 'none') { + $deployableEntities = $entities; + } elseif ($excludedEntities[0] !== 'none') { + $deployableEntities = array_diff($entities, $excludedEntities); + } elseif ($includedEntities[0] !== 'all') { + $deployableEntities = array_intersect($entities, $includedEntities); + } + + return $deployableEntities; + } + + /** + * {@inheritdoc} + * @throws \InvalidArgumentException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->input = $input; $filesUtil = $this->objectManager->create(Files::class); - $deployer = $this->objectManager->create( - 'Magento\Deploy\Model\Deployer', - ['filesUtil' => $filesUtil, 'output' => $output, 'isDryRun' => $options[self::DRY_RUN_OPTION]] + list ($deployableLanguages, $deployableAreaThemeMap, $requestedThemes) + = $this->prepareDeployableEntities($filesUtil); + + $output->writeln("Requested languages: " . implode(', ', $deployableLanguages)); + $output->writeln("Requested areas: " . implode(', ', array_keys($deployableAreaThemeMap))); + $output->writeln("Requested themes: " . implode(', ', $requestedThemes)); + + /** @var $deployManager DeployManager */ + $deployManager = $this->objectManager->create( + DeployManager::class, + [ + 'output' => $output, + 'options' => $this->input->getOptions(), + ] ); - return $deployer->deploy($this->objectManagerFactory, $languages); + + foreach ($deployableAreaThemeMap as $area => $themes) { + foreach ($deployableLanguages as $locale) { + foreach ($themes as $themePath) { + $deployManager->addPack($area, $themePath, $locale); + } + } + } + + $this->mockCache(); + return $deployManager->deploy(); + } + + /** + * @param Files $filesUtil + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function prepareDeployableEntities($filesUtil) + { + $magentoAreas = []; + $magentoThemes = []; + $magentoLanguages = [self::DEFAULT_LANGUAGE_VALUE]; + $areaThemeMap = []; + $files = $filesUtil->getStaticPreProcessingFiles(); + foreach ($files as $info) { + list($area, $themePath, $locale) = $info; + if ($themePath) { + $areaThemeMap[$area][$themePath] = $themePath; + } + if ($themePath && $area && !in_array($area, $magentoAreas)) { + $magentoAreas[] = $area; + } + if ($locale && !in_array($locale, $magentoLanguages)) { + $magentoLanguages[] = $locale; + } + if ($themePath && !in_array($themePath, $magentoThemes)) { + $magentoThemes[] = $themePath; + } + } + + $areasInclude = $this->input->getOption(Options::AREA); + $areasExclude = $this->input->getOption(Options::EXCLUDE_AREA); + $this->checkAreasInput($magentoAreas, $areasInclude, $areasExclude); + $deployableAreas = $this->getDeployableEntities($magentoAreas, $areasInclude, $areasExclude); + + $languagesInclude = $this->input->getArgument(self::LANGUAGES_ARGUMENT) + ?: $this->input->getOption(Options::LANGUAGE); + $languagesExclude = $this->input->getOption(Options::EXCLUDE_LANGUAGE); + $this->checkLanguagesInput($languagesInclude, $languagesExclude); + $deployableLanguages = $languagesInclude[0] == 'all' + ? $this->getDeployableEntities($magentoLanguages, $languagesInclude, $languagesExclude) + : $languagesInclude; + + $themesInclude = $this->input->getOption(Options::THEME); + $themesExclude = $this->input->getOption(Options::EXCLUDE_THEME); + $this->checkThemesInput($magentoThemes, $themesInclude, $themesExclude); + $deployableThemes = $this->getDeployableEntities($magentoThemes, $themesInclude, $themesExclude); + + $deployableAreaThemeMap = []; + $requestedThemes = []; + foreach ($areaThemeMap as $area => $themes) { + if (in_array($area, $deployableAreas) && $themes = array_intersect($themes, $deployableThemes)) { + $deployableAreaThemeMap[$area] = $themes; + $requestedThemes += $themes; + } + } + + return [$deployableLanguages, $deployableAreaThemeMap, $requestedThemes]; + } + + /** + * Mock Cache class with dummy implementation + * + * @return void + */ + private function mockCache() + { + $this->objectManager->configure([ + 'preferences' => [ + Cache::class => DummyCache::class + ] + ]); } } diff --git a/app/code/Magento/Deploy/Console/Command/DeployStaticOptionsInterface.php b/app/code/Magento/Deploy/Console/Command/DeployStaticOptionsInterface.php new file mode 100644 index 0000000000000..ff37aacc6e388 --- /dev/null +++ b/app/code/Magento/Deploy/Console/Command/DeployStaticOptionsInterface.php @@ -0,0 +1,95 @@ +objectManager = $objectManager; + } + + /** + * Gets list of command classes + * + * @return string[] + */ + protected function getCommandsClasses() + { + return [ + \Magento\Deploy\Console\Command\DeployStaticContentCommand::class + ]; + } + + /** + * {@inheritdoc} + */ + public function getCommands() + { + $commands = []; + foreach ($this->getCommandsClasses() as $class) { + if (class_exists($class)) { + $commands[] = $this->objectManager->get($class); + } else { + throw new \Exception('Class ' . $class . ' does not exist'); + } + } + return $commands; + } +} diff --git a/app/code/Magento/Deploy/Model/Deploy/DeployInterface.php b/app/code/Magento/Deploy/Model/Deploy/DeployInterface.php new file mode 100644 index 0000000000000..e2eeb1032baa6 --- /dev/null +++ b/app/code/Magento/Deploy/Model/Deploy/DeployInterface.php @@ -0,0 +1,23 @@ + Options::NO_JAVASCRIPT, + 'map' => Options::NO_JAVASCRIPT, + 'css' => Options::NO_CSS, + 'less' => Options::NO_LESS, + 'html' => Options::NO_HTML, + 'htm' => Options::NO_HTML, + 'jpg' => Options::NO_IMAGES, + 'jpeg' => Options::NO_IMAGES, + 'gif' => Options::NO_IMAGES, + 'png' => Options::NO_IMAGES, + 'ico' => Options::NO_IMAGES, + 'svg' => Options::NO_IMAGES, + 'eot' => Options::NO_FONTS, + 'ttf' => Options::NO_FONTS, + 'woff' => Options::NO_FONTS, + 'woff2' => Options::NO_FONTS, + 'md' => Options::NO_MISC, + 'jbf' => Options::NO_MISC, + 'csv' => Options::NO_MISC, + 'json' => Options::NO_MISC, + 'txt' => Options::NO_MISC, + 'htc' => Options::NO_MISC, + 'swf' => Options::NO_MISC, + 'LICENSE' => Options::NO_MISC, + '' => Options::NO_MISC, + ]; + + /** + * @param OutputInterface $output + * @param JsTranslationConfig $jsTranslationConfig + * @param Minification $minification + * @param \Magento\Framework\View\Asset\Repository $assetRepo + * @param \Magento\Framework\View\Asset\RepositoryFactory $assetRepoFactory + * @param \Magento\RequireJs\Model\FileManagerFactory $fileManagerFactory + * @param \Magento\Framework\RequireJs\ConfigFactory $requireJsConfigFactory + * @param Publisher $assetPublisher + * @param \Magento\Framework\View\Asset\Bundle\Manager $bundleManager + * @param ThemeProviderInterface $themeProvider + * @param LoggerInterface $logger + * @param Files $filesUtil + * @param \Magento\Framework\View\DesignInterfaceFactory $designFactory + * @param \Magento\Framework\Locale\ResolverInterface $localeResolver + * @param array $alternativeSources + * @param array $options + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + OutputInterface $output, + JsTranslationConfig $jsTranslationConfig, + Minification $minification, + \Magento\Framework\View\Asset\Repository $assetRepo, + \Magento\Framework\View\Asset\RepositoryFactory $assetRepoFactory, + \Magento\RequireJs\Model\FileManagerFactory $fileManagerFactory, + \Magento\Framework\RequireJs\ConfigFactory $requireJsConfigFactory, + \Magento\Framework\App\View\Asset\Publisher $assetPublisher, + \Magento\Framework\View\Asset\Bundle\Manager $bundleManager, + \Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider, + LoggerInterface $logger, + Files $filesUtil, + \Magento\Framework\View\DesignInterfaceFactory $designFactory, + \Magento\Framework\Locale\ResolverInterface $localeResolver, + array $alternativeSources, + $options = [] + ) { + $this->output = $output; + $this->assetRepo = $assetRepo; + $this->assetPublisher = $assetPublisher; + $this->bundleManager = $bundleManager; + $this->filesUtil = $filesUtil; + $this->jsTranslationConfig = $jsTranslationConfig; + $this->minification = $minification; + $this->logger = $logger; + $this->assetRepoFactory = $assetRepoFactory; + $this->fileManagerFactory = $fileManagerFactory; + $this->requireJsConfigFactory = $requireJsConfigFactory; + $this->themeProvider = $themeProvider; + $this->alternativeSources = array_map( + function (AlternativeSourceInterface $alternativeSource) { + return $alternativeSource; + }, + $alternativeSources + ); + $this->designFactory = $designFactory; + $this->localeResolver = $localeResolver; + $this->options = $options; + } + + /** + * {@inheritdoc} + */ + public function deploy($area, $themePath, $locale) + { + $this->output->writeln("=== {$area} -> {$themePath} -> {$locale} ==="); + + // emulate application locale needed for correct file path resolving + $this->localeResolver->setLocale($locale); + + $this->deployRequireJsConfig($area, $themePath); + $this->deployAppFiles($area, $themePath, $locale); + $this->deployLibFiles($area, $themePath, $locale); + + if (!$this->getOption(Options::NO_JAVASCRIPT)) { + if ($this->jsTranslationConfig->dictionaryEnabled()) { + $dictionaryFileName = $this->jsTranslationConfig->getDictionaryFileName(); + $this->deployFile($dictionaryFileName, $area, $themePath, $locale, null); + } + } + if (!$this->getOption(Options::NO_JAVASCRIPT)) { + $this->bundleManager->flush(); + } + $this->output->writeln("\nSuccessful: {$this->count} files; errors: {$this->errorCount}\n---\n"); + + return $this->errorCount ? Cli::RETURN_FAILURE : Cli::RETURN_SUCCESS; + } + + /** + * @param string $area + * @param string $themePath + * @return void + */ + private function deployRequireJsConfig($area, $themePath) + { + if (!$this->getOption(Options::DRY_RUN) && !$this->getOption(Options::NO_JAVASCRIPT)) { + + /** @var \Magento\Framework\View\Design\ThemeInterface $theme */ + $theme = $this->getThemeList()->getThemeByFullPath($area . '/' . $themePath); + $design = $this->designFactory->create()->setDesignTheme($theme, $area); + $assetRepo = $this->assetRepoFactory->create(['design' => $design]); + /** @var \Magento\RequireJs\Model\FileManager $fileManager */ + $fileManager = $this->fileManagerFactory->create( + [ + 'config' => $this->requireJsConfigFactory->create( + [ + 'assetRepo' => $assetRepo, + 'design' => $design, + ] + ), + 'assetRepo' => $assetRepo, + ] + ); + $fileManager->createRequireJsConfigAsset(); + if ($this->minification->isEnabled('js')) { + $fileManager->createMinResolverAsset(); + } + } + } + + /** + * @param string $area + * @param string $themePath + * @param string $locale + * @return void + */ + private function deployAppFiles($area, $themePath, $locale) + { + foreach ($this->filesUtil->getStaticPreProcessingFiles() as $info) { + list($fileArea, $fileTheme, , $module, $filePath, $fullPath) = $info; + + if ($this->checkSkip($filePath)) { + continue; + } + + if ($this->isCanBeDeployed($fileArea, $fileTheme, $area, $themePath)) { + $compiledFile = $this->deployFile( + $filePath, + $area, + $themePath, + $locale, + $module, + $fullPath + ); + if ($compiledFile !== '' && !$this->checkSkip($compiledFile)) { + $this->deployFile($compiledFile, $area, $themePath, $locale, $module, $fullPath); + } + } + } + } + + /** + * @param string $fileArea + * @param string $fileTheme + * @param string $area + * @param string $themePath + * @return bool + */ + private function isCanBeDeployed($fileArea, $fileTheme, $area, $themePath) + { + return ($fileArea == $area || $fileArea == 'base') + && ($fileTheme == '' || $fileTheme == $themePath + || in_array( + $fileArea . Theme::THEME_PATH_SEPARATOR . $fileTheme, + $this->findAncestors($area . Theme::THEME_PATH_SEPARATOR . $themePath) + ) + ); + } + + /** + * @param string $area + * @param string $themePath + * @param string $locale + * @return void + */ + private function deployLibFiles($area, $themePath, $locale) + { + foreach ($this->filesUtil->getStaticLibraryFiles() as $filePath) { + + if ($this->checkSkip($filePath)) { + continue; + } + + $compiledFile = $this->deployFile($filePath, $area, $themePath, $locale, null); + + if ($compiledFile !== '' && !$this->checkSkip($compiledFile)) { + $this->deployFile($compiledFile, $area, $themePath, $locale, null); + } + } + } + + /** + * Deploy a static view file + * + * @param string $filePath + * @param string $area + * @param string $themePath + * @param string $locale + * @param string $module + * @param string|null $fullPath + * @return string + * + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function deployFile($filePath, $area, $themePath, $locale, $module, $fullPath = null) + { + $compiledFile = ''; + $extension = pathinfo($filePath, PATHINFO_EXTENSION); + + foreach ($this->alternativeSources as $name => $alternative) { + if (in_array($extension, $alternative->getAlternativesExtensionsNames(), true) + && strpos(basename($filePath), '_') !== 0 + ) { + $compiledFile = substr($filePath, 0, strlen($filePath) - strlen($extension) - 1); + $compiledFile = $compiledFile . '.' . $name; + } + } + + if ($this->output->isVeryVerbose()) { + $logMessage = "Processing file '$filePath' for area '$area', theme '$themePath', locale '$locale'"; + if ($module) { + $logMessage .= ", module '$module'"; + } + $this->output->writeln($logMessage); + } + + try { + $asset = $this->assetRepo->createAsset( + $filePath, + ['area' => $area, 'theme' => $themePath, 'locale' => $locale, 'module' => $module] + ); + if ($this->output->isVeryVerbose()) { + $this->output->writeln("\tDeploying the file to '{$asset->getPath()}'"); + } else { + $this->output->write('.'); + } + if ($this->getOption(Options::DRY_RUN)) { + $asset->getContent(); + } else { + $this->assetPublisher->publish($asset); + if (!$this->getOption(Options::NO_JAVASCRIPT)) { + $this->bundleManager->addAsset($asset); + } + } + $this->count++; + } catch (ContentProcessorException $exception) { + $pathInfo = $fullPath ?: $filePath; + $errorMessage = __('Compilation from source: ') . $pathInfo . PHP_EOL . $exception->getMessage(); + $this->errorCount++; + $this->output->write(PHP_EOL . PHP_EOL . $errorMessage . PHP_EOL, true); + + $this->logger->critical($errorMessage); + } catch (\Exception $exception) { + $this->output->write('.'); + if ($this->output->isVerbose()) { + $this->output->writeln($exception->getTraceAsString()); + } + $this->errorCount++; + } + + return $compiledFile; + } + + /** + * @param string $name + * @return mixed|null + */ + private function getOption($name) + { + return isset($this->options[$name]) ? $this->options[$name] : null; + } + + /** + * Check if skip flag is affecting file by extension + * + * @param string $filePath + * @return boolean + */ + private function checkSkip($filePath) + { + if ($filePath != '.') { + $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); + $option = isset(self::$fileExtensionOptionMap[$ext]) ? self::$fileExtensionOptionMap[$ext] : null; + + return $option ? $this->getOption($option) : false; + } + + return false; + } + + /** + * Find ancestor themes' full paths + * + * @param string $themeFullPath + * @return string[] + */ + private function findAncestors($themeFullPath) + { + $theme = $this->themeProvider->getThemeByFullPath($themeFullPath); + $ancestors = $theme->getInheritedThemes(); + $ancestorThemeFullPath = []; + foreach ($ancestors as $ancestor) { + $ancestorThemeFullPath[] = $ancestor->getFullPath(); + } + return $ancestorThemeFullPath; + } + + /** + * @deprecated + * @return ListInterface + */ + private function getThemeList() + { + if ($this->themeList === null) { + $this->themeList = ObjectManager::getInstance()->get(ListInterface::class); + } + return $this->themeList; + } +} diff --git a/app/code/Magento/Deploy/Model/Deploy/LocaleQuickDeploy.php b/app/code/Magento/Deploy/Model/Deploy/LocaleQuickDeploy.php new file mode 100644 index 0000000000000..0d990b555cb66 --- /dev/null +++ b/app/code/Magento/Deploy/Model/Deploy/LocaleQuickDeploy.php @@ -0,0 +1,152 @@ +filesystem = $filesystem; + $this->output = $output; + $this->options = $options; + } + + /** + * @return WriteInterface + */ + private function getStaticDirectory() + { + if ($this->staticDirectory === null) { + $this->staticDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW); + } + + return $this->staticDirectory; + } + + /** + * {@inheritdoc} + */ + public function deploy($area, $themePath, $locale) + { + if (isset($this->options[Options::DRY_RUN]) && $this->options[Options::DRY_RUN]) { + return Cli::RETURN_SUCCESS; + } + + $this->output->writeln("=== {$area} -> {$themePath} -> {$locale} ==="); + + if (!isset($this->options[self::DEPLOY_BASE_LOCALE])) { + throw new \InvalidArgumentException('Deploy base locale must be set for Quick Deploy'); + } + $processedFiles = 0; + $errorAmount = 0; + + $baseLocale = $this->options[self::DEPLOY_BASE_LOCALE]; + $newLocalePath = $this->getLocalePath($area, $themePath, $locale); + $baseLocalePath = $this->getLocalePath($area, $themePath, $baseLocale); + $baseRequireJsPath = RequireJsConfig::DIR_NAME . DIRECTORY_SEPARATOR . $baseLocalePath; + $newRequireJsPath = RequireJsConfig::DIR_NAME . DIRECTORY_SEPARATOR . $newLocalePath; + + $this->deleteLocaleResource($newLocalePath); + $this->deleteLocaleResource($newRequireJsPath); + + if (isset($this->options[Options::SYMLINK_LOCALE]) && $this->options[Options::SYMLINK_LOCALE]) { + $this->getStaticDirectory()->createSymlink($baseLocalePath, $newLocalePath); + $this->getStaticDirectory()->createSymlink($baseRequireJsPath, $newRequireJsPath); + + $this->output->writeln("\nSuccessful symlinked\n---\n"); + } else { + $localeFiles = array_merge( + $this->getStaticDirectory()->readRecursively($baseLocalePath), + $this->getStaticDirectory()->readRecursively($baseRequireJsPath) + ); + foreach ($localeFiles as $path) { + if ($this->getStaticDirectory()->isFile($path)) { + $destination = $this->replaceLocaleInPath($path, $baseLocale, $locale); + $this->getStaticDirectory()->copyFile($path, $destination); + $processedFiles++; + } + } + + $this->output->writeln("\nSuccessful copied: {$processedFiles} files; errors: {$errorAmount}\n---\n"); + } + + return Cli::RETURN_SUCCESS; + } + + /** + * @param string $path + * @return void + */ + private function deleteLocaleResource($path) + { + if ($this->getStaticDirectory()->isExist($path)) { + $absolutePath = $this->getStaticDirectory()->getAbsolutePath($path); + if (is_link($absolutePath)) { + $this->getStaticDirectory()->getDriver()->deleteFile($absolutePath); + } else { + $this->getStaticDirectory()->getDriver()->deleteDirectory($absolutePath); + } + } + } + + /** + * @param string $path + * @param string $search + * @param string $replace + * @return string + */ + private function replaceLocaleInPath($path, $search, $replace) + { + return preg_replace('~' . $search . '~', $replace, $path, 1); + } + + /** + * @param string $area + * @param string $themePath + * @param string $locale + * @return string + */ + private function getLocalePath($area, $themePath, $locale) + { + return $area . DIRECTORY_SEPARATOR . $themePath . DIRECTORY_SEPARATOR . $locale; + } +} diff --git a/app/code/Magento/Deploy/Model/Deploy/TemplateMinifier.php b/app/code/Magento/Deploy/Model/Deploy/TemplateMinifier.php new file mode 100644 index 0000000000000..4693afeefdc1f --- /dev/null +++ b/app/code/Magento/Deploy/Model/Deploy/TemplateMinifier.php @@ -0,0 +1,49 @@ +filesUtils = $filesUtils; + $this->htmlMinifier = $htmlMinifier; + } + + /** + * Minify template files + * @return int + */ + public function minifyTemplates() + { + $minified = 0; + foreach ($this->filesUtils->getPhtmlFiles(false, false) as $template) { + $this->htmlMinifier->minify($template); + $minified++; + } + return $minified; + } +} diff --git a/app/code/Magento/Deploy/Model/DeployManager.php b/app/code/Magento/Deploy/Model/DeployManager.php new file mode 100644 index 0000000000000..c2c8f0bd4e535 --- /dev/null +++ b/app/code/Magento/Deploy/Model/DeployManager.php @@ -0,0 +1,205 @@ +output = $output; + $this->options = $options; + $this->versionStorage = $versionStorage; + $this->deployStrategyProviderFactory = $deployStrategyProviderFactory; + $this->processQueueManagerFactory = $processQueueManagerFactory; + $this->templateMinifier = $templateMinifier; + $this->state = $state; + $this->idDryRun = !empty($this->options[Options::DRY_RUN]); + } + + /** + * Add package tie to area and theme + * + * @param string $area + * @param string $themePath + * @param string $locale + * @return void + */ + public function addPack($area, $themePath, $locale) + { + $this->packages[$area . '-' . $themePath][$locale] = [$area, $themePath]; + } + + /** + * Deploy local packages with chosen deploy strategy + * @return int + */ + public function deploy() + { + if ($this->idDryRun) { + $this->output->writeln('Dry run. Nothing will be recorded to the target directory.'); + } else { + $version = (new \DateTime())->getTimestamp(); + $this->versionStorage->save($version); + } + + /** @var DeployStrategyProvider $strategyProvider */ + $strategyProvider = $this->deployStrategyProviderFactory->create( + ['output' => $this->output, 'options' => $this->options] + ); + + if ($this->isCanBeParalleled()) { + $result = $this->runInParallel($strategyProvider); + } else { + $result = 0; + foreach ($this->packages as $package) { + $locales = array_keys($package); + list($area, $themePath) = current($package); + foreach ($strategyProvider->getDeployStrategies($area, $themePath, $locales) as $locale => $strategy) { + $result |= $this->state->emulateAreaCode( + $area, + [$strategy, 'deploy'], + [$area, $themePath, $locale] + ); + } + } + } + + $this->minifyTemplates(); + if (!$this->idDryRun) { + $this->output->writeln("New version of deployed files: {$version}"); + } + + return $result; + } + + /** + * @return void + */ + private function minifyTemplates() + { + $noHtmlMinify = isset($this->options[Options::NO_HTML_MINIFY]) ? $this->options[Options::NO_HTML_MINIFY] : null; + if (!$noHtmlMinify && !$this->idDryRun) { + $this->output->writeln('=== Minify templates ==='); + $minified = $this->templateMinifier->minifyTemplates(); + $this->output->writeln("\nSuccessful: {$minified} files modified\n---\n"); + } + } + + /** + * @param DeployStrategyProvider $strategyProvider + * @return int + */ + private function runInParallel($strategyProvider) + { + $processQueueManager = $this->processQueueManagerFactory->create( + ['maxProcesses' => $this->getProcessesAmount()] + ); + foreach ($this->packages as $package) { + $locales = array_keys($package); + list($area, $themePath) = current($package); + $baseStrategy = null; + $dependentStrategy = []; + foreach ($strategyProvider->getDeployStrategies($area, $themePath, $locales) as $locale => $strategy) { + $deploymentFunc = function () use ($area, $themePath, $locale, $strategy) { + return $this->state->emulateAreaCode($area, [$strategy, 'deploy'], [$area, $themePath, $locale]); + }; + if (null === $baseStrategy) { + $baseStrategy = $deploymentFunc; + } else { + $dependentStrategy[] = $deploymentFunc; + } + + } + $processQueueManager->addTaskToQueue($baseStrategy, $dependentStrategy); + } + + return $processQueueManager->process(); + } + + /** + * @return bool + */ + private function isCanBeParalleled() + { + return function_exists('pcntl_fork') && $this->getProcessesAmount() > 1; + } + + /** + * @return int + */ + private function getProcessesAmount() + { + return isset($this->options[Options::JOBS_AMOUNT]) ? (int)$this->options[Options::JOBS_AMOUNT] : 0; + } +} diff --git a/app/code/Magento/Deploy/Model/DeployStrategyFactory.php b/app/code/Magento/Deploy/Model/DeployStrategyFactory.php new file mode 100644 index 0000000000000..536f344e600cc --- /dev/null +++ b/app/code/Magento/Deploy/Model/DeployStrategyFactory.php @@ -0,0 +1,52 @@ +objectManager = $objectManager; + } + + /** + * @param string $type + * @param array $arguments + * @return DeployInterface + * @throws InputException + */ + public function create($type, array $arguments = []) + { + $strategyMap = [ + self::DEPLOY_STRATEGY_STANDARD => Deploy\LocaleDeploy::class, + self::DEPLOY_STRATEGY_QUICK => Deploy\LocaleQuickDeploy::class, + ]; + + if (!isset($strategyMap[$type])) { + throw new InputException(__('Wrong deploy strategy type: %1', $type)); + } + + return $this->objectManager->create($strategyMap[$type], $arguments); + } +} diff --git a/app/code/Magento/Deploy/Model/DeployStrategyProvider.php b/app/code/Magento/Deploy/Model/DeployStrategyProvider.php new file mode 100644 index 0000000000000..cf6c1f1be9ad2 --- /dev/null +++ b/app/code/Magento/Deploy/Model/DeployStrategyProvider.php @@ -0,0 +1,193 @@ +rulePool = $rulePool; + $this->design = $design; + $this->output = $output; + $this->options = $options; + $this->deployStrategyFactory = $deployStrategyFactory; + } + + /** + * @param string $area + * @param string $themePath + * @param array $locales + * @return DeployInterface[] + */ + public function getDeployStrategies($area, $themePath, array $locales) + { + if (count($locales) == 1) { + $locale = current($locales); + return [$locale => $this->getDeployStrategy(DeployStrategyFactory::DEPLOY_STRATEGY_STANDARD)]; + } + + $baseLocale = null; + $deployStrategies = []; + + foreach ($locales as $locale) { + $hasCustomization = false; + foreach ($this->getCustomizationDirectories($area, $themePath, $locale) as $directory) { + if (glob($directory . DIRECTORY_SEPARATOR . '*', GLOB_NOSORT)) { + $hasCustomization = true; + break; + } + } + if ($baseLocale === null && !$hasCustomization) { + $baseLocale = $locale; + } else { + $deployStrategies[$locale] = $hasCustomization + ? DeployStrategyFactory::DEPLOY_STRATEGY_STANDARD + : DeployStrategyFactory::DEPLOY_STRATEGY_QUICK; + } + } + $deployStrategies = array_merge( + [$baseLocale => DeployStrategyFactory::DEPLOY_STRATEGY_STANDARD], + $deployStrategies + ); + + return array_map(function ($strategyType) use ($area, $baseLocale) { + return $this->getDeployStrategy($strategyType, $baseLocale); + }, $deployStrategies); + } + + /** + * @param array $params + * @return array + */ + private function getLocaleDirectories($params) + { + $dirs = $this->getFallbackRule()->getPatternDirs($params); + + return array_filter($dirs, function ($dir) { + return strpos($dir, Dir::MODULE_I18N_DIR); + }); + } + + /** + * Get directories which can contains theme customization + * @param string $area + * @param string $themePath + * @param string $locale + * @return array + */ + private function getCustomizationDirectories($area, $themePath, $locale) + { + $customizationDirectories = []; + $this->design->setDesignTheme($themePath, $area); + + $params = ['area' => $area, 'theme' => $this->design->getDesignTheme(), 'locale' => $locale]; + foreach ($this->getLocaleDirectories($params) as $patternDir) { + $customizationDirectories[] = $patternDir; + } + + if ($this->moduleDirectories === null) { + $this->moduleDirectories = []; + $componentRegistrar = new ComponentRegistrar(); + $this->moduleDirectories = array_keys($componentRegistrar->getPaths(ComponentRegistrar::MODULE)); + } + + foreach ($this->moduleDirectories as $moduleDir) { + $params['module_name'] = $moduleDir; + $patternDirs = $this->getLocaleDirectories($params); + foreach ($patternDirs as $patternDir) { + $customizationDirectories[] = $patternDir; + } + } + + return $customizationDirectories; + } + + /** + * @return \Magento\Framework\View\Design\Fallback\Rule\RuleInterface + */ + private function getFallbackRule() + { + if (null === $this->fallBackRule) { + $this->fallBackRule = $this->rulePool->getRule(RulePool::TYPE_STATIC_FILE); + } + + return $this->fallBackRule; + } + + /** + * @param string $type + * @param null|string $baseLocale + * @return DeployInterface + */ + private function getDeployStrategy($type, $baseLocale = null) + { + $options = $this->options; + if ($baseLocale) { + $options[DeployInterface::DEPLOY_BASE_LOCALE] = $baseLocale; + } + + return $this->deployStrategyFactory->create( + $type, + ['output' => $this->output, 'options' => $options] + ); + } +} diff --git a/app/code/Magento/Deploy/Model/Deployer.php b/app/code/Magento/Deploy/Model/Deployer.php index 5ce8251db1e8b..53a2a7fec21c2 100644 --- a/app/code/Magento/Deploy/Model/Deployer.php +++ b/app/code/Magento/Deploy/Model/Deployer.php @@ -1,78 +1,46 @@ filesUtil = $filesUtil; $this->output = $output; - $this->versionStorage = $versionStorage; - $this->isDryRun = $isDryRun; - $this->jsTranslationConfig = $jsTranslationConfig; - $this->parentTheme = []; - - array_map( - function (AlternativeSourceInterface $alternative) { - }, - $alternativeSources - ); - $this->alternativeSources = $alternativeSources; - } - - /** - * Populate all static view files for specified root path and list of languages - * - * @param ObjectManagerFactory $omFactory - * @param array $locales - * @return int - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function deploy(ObjectManagerFactory $omFactory, array $locales) - { - $this->omFactory = $omFactory; - if ($this->isDryRun) { - $this->output->writeln('Dry run. Nothing will be recorded to the target directory.'); - } - $langList = implode(', ', $locales); - $this->output->writeln("Requested languages: {$langList}"); - $libFiles = $this->filesUtil->getStaticLibraryFiles(); - list($areas, $appFiles) = $this->collectAppFiles($locales); - foreach ($areas as $area => $themes) { - $this->emulateApplicationArea($area); - foreach ($locales as $locale) { - $this->emulateApplicationLocale($locale, $area); - foreach ($themes as $themePath) { - $this->output->writeln("=== {$area} -> {$themePath} -> {$locale} ==="); - $this->count = 0; - $this->errorCount = 0; - /** @var \Magento\Theme\Model\View\Design $design */ - $design = $this->objectManager->create('Magento\Theme\Model\View\Design'); - $design->setDesignTheme($themePath, $area); - $assetRepo = $this->objectManager->create( - 'Magento\Framework\View\Asset\Repository', - [ - 'design' => $design, - ] - ); - /** @var \Magento\RequireJs\Model\FileManager $fileManager */ - $fileManager = $this->objectManager->create( - 'Magento\RequireJs\Model\FileManager', - [ - 'config' => $this->objectManager->create( - 'Magento\Framework\RequireJs\Config', - [ - 'assetRepo' => $assetRepo, - 'design' => $design, - ] - ), - 'assetRepo' => $assetRepo, - ] - ); - $fileManager->createRequireJsConfigAsset(); - foreach ($appFiles as $info) { - list($fileArea, $fileTheme, , $module, $filePath) = $info; - if (($fileArea == $area || $fileArea == 'base') && - ($fileTheme == '' || $fileTheme == $themePath || - in_array( - $fileArea . Theme::THEME_PATH_SEPARATOR . $fileTheme, - $this->findAncestors($area . Theme::THEME_PATH_SEPARATOR . $themePath) - )) - ) { - $compiledFile = $this->deployFile($filePath, $area, $themePath, $locale, $module); - if ($compiledFile !== '') { - $this->deployFile($compiledFile, $area, $themePath, $locale, $module); - } - } - } - foreach ($libFiles as $filePath) { - $compiledFile = $this->deployFile($filePath, $area, $themePath, $locale, null); - if ($compiledFile !== '') { - $this->deployFile($compiledFile, $area, $themePath, $locale, null); - } - } - if ($this->jsTranslationConfig->dictionaryEnabled()) { - $dictionaryFileName = $this->jsTranslationConfig->getDictionaryFileName(); - $this->deployFile($dictionaryFileName, $area, $themePath, $locale, null); - } - $fileManager->clearBundleJsPool(); - $this->bundleManager->flush(); - $this->output->writeln("\nSuccessful: {$this->count} files; errors: {$this->errorCount}\n---\n"); - } - } - } - $this->output->writeln('=== Minify templates ==='); - $this->count = 0; - foreach ($this->filesUtil->getPhtmlFiles(false, false) as $template) { - $this->htmlMinifier->minify($template); - if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { - $this->output->writeln($template . " minified\n"); - } else { - $this->output->write('.'); - } - $this->count++; + $this->deployManagerFactory = $deployManagerFactory; + if (is_array($options)) { + $this->options = $options; + } else { + // backward compatibility support + $this->options = [DeployStaticOptionsInterface::DRY_RUN => (bool)$options]; } - $this->output->writeln("\nSuccessful: {$this->count} files modified\n---\n"); - $version = (new \DateTime())->getTimestamp(); - $this->output->writeln("New version of deployed files: {$version}"); - if (!$this->isDryRun) { - $this->versionStorage->save($version); - } - if ($this->errorCount > 0) { - // we must have an exit code higher than zero to indicate something was wrong - return \Magento\Framework\Console\Cli::RETURN_FAILURE; - } - return \Magento\Framework\Console\Cli::RETURN_SUCCESS; } /** - * Accumulate all static view files in the application and record all found areas, themes and languages - * - * Returns an array of areas and files with meta information - * - * @param array $requestedLocales - * @return array + * @return \Magento\Deploy\Model\DeployManagerFactory */ - private function collectAppFiles($requestedLocales) + private function getDeployManagerFactory() { - $areas = []; - $locales = []; - $files = $this->filesUtil->getStaticPreProcessingFiles(); - foreach ($files as $info) { - list($area, $themePath, $locale) = $info; - if ($themePath) { - $areas[$area][$themePath] = $themePath; - } - if ($locale) { - $locales[$locale] = $locale; - } - } - foreach ($requestedLocales as $locale) { - unset($locales[$locale]); - } - if (!empty($locales)) { - $langList = implode(', ', $locales); - $this->output->writeln( - "WARNING: there were files for the following languages detected in the file system: {$langList}." - . ' These languages were not requested, so the files will not be populated.' - ); + if (null === $this->deployManagerFactory) { + $this->deployManagerFactory = ObjectManager::getInstance()->get(DeployManagerFactory::class); } - return [$areas, $files]; + return $this->deployManagerFactory; } /** - * Emulate application area and various services that are necessary for populating files + * Populate all static view files for specified root path and list of languages * - * @param string $areaCode - * @return void + * @param ObjectManagerFactory $omFactory + * @param array $locales + * @param array $deployableAreaThemeMap + * @return int + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @deprecated */ - private function emulateApplicationArea($areaCode) + public function deploy(ObjectManagerFactory $omFactory, array $locales, array $deployableAreaThemeMap = []) { - $this->objectManager = $this->omFactory->create( - [\Magento\Framework\App\State::PARAM_MODE => \Magento\Framework\App\State::MODE_DEFAULT] + /** @var DeployManager $deployerManager */ + $deployerManager = $this->getDeployManagerFactory()->create( + ['options' => $this->options, 'output' => $this->output] ); - /** @var \Magento\Framework\App\State $appState */ - $appState = $this->objectManager->get('Magento\Framework\App\State'); - $appState->setAreaCode($areaCode); - $this->assetRepo = $this->objectManager->get('Magento\Framework\View\Asset\Repository'); - $this->assetPublisher = $this->objectManager->create('Magento\Framework\App\View\Asset\Publisher'); - $this->htmlMinifier = $this->objectManager->get('Magento\Framework\View\Template\Html\MinifierInterface'); - $this->bundleManager = $this->objectManager->get('Magento\Framework\View\Asset\Bundle\Manager'); + foreach ($deployableAreaThemeMap as $area => $themes) { + foreach ($locales as $locale) { + foreach ($themes as $themePath) { + $deployerManager->addPack($area, $themePath, $locale); + } + } + } + return $deployerManager->deploy(); } /** @@ -276,112 +118,10 @@ private function emulateApplicationArea($areaCode) * @param string $locale * @param string $area * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @deprecated */ protected function emulateApplicationLocale($locale, $area) { - /** @var \Magento\Framework\TranslateInterface $translator */ - $translator = $this->objectManager->get('Magento\Framework\TranslateInterface'); - $translator->setLocale($locale); - $translator->loadData($area, true); - /** @var \Magento\Framework\Locale\ResolverInterface $localeResolver */ - $localeResolver = $this->objectManager->get('Magento\Framework\Locale\ResolverInterface'); - $localeResolver->setLocale($locale); - } - - /** - * Deploy a static view file - * - * @param string $filePath - * @param string $area - * @param string $themePath - * @param string $locale - * @param string $module - * @return string - * @throws \InvalidArgumentException - * @throws LocalizedException - * - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - private function deployFile($filePath, $area, $themePath, $locale, $module) - { - $compiledFile = ''; - $extension = pathinfo($filePath, PATHINFO_EXTENSION); - - foreach ($this->alternativeSources as $name => $alternative) { - if (in_array($extension, $alternative->getAlternativesExtensionsNames(), true) - && strpos(basename($filePath), '_') !== 0 - ) { - $compiledFile = substr($filePath, 0, strlen($filePath) - strlen($extension) - 1); - $compiledFile = $compiledFile . '.' . $name; - } - } - - if ($this->output->isVeryVerbose()) { - $logMessage = "Processing file '$filePath' for area '$area', theme '$themePath', locale '$locale'"; - if ($module) { - $logMessage .= ", module '$module'"; - } - $this->output->writeln($logMessage); - } - - try { - $asset = $this->assetRepo->createAsset( - $filePath, - ['area' => $area, 'theme' => $themePath, 'locale' => $locale, 'module' => $module] - ); - if ($this->output->isVeryVerbose()) { - $this->output->writeln("\tDeploying the file to '{$asset->getPath()}'"); - } else { - $this->output->write('.'); - } - if ($this->isDryRun) { - $asset->getContent(); - } else { - $this->assetPublisher->publish($asset); - $this->bundleManager->addAsset($asset); - } - $this->count++; - } catch (ContentProcessorException $exception) { - throw $exception; - } catch (\Exception $exception) { - $this->output->write('.'); - $this->verboseLog($exception->getTraceAsString()); - $this->errorCount++; - } - - return $compiledFile; - } - - /** - * Find ancestor themes' full paths - * - * @param string $themeFullPath - * @return string[] - */ - private function findAncestors($themeFullPath) - { - /** @var \Magento\Framework\View\Design\Theme\ListInterface $themeCollection */ - $themeCollection = $this->objectManager->get('Magento\Framework\View\Design\Theme\ListInterface'); - $theme = $themeCollection->getThemeByFullPath($themeFullPath); - $ancestors = $theme->getInheritedThemes(); - $ancestorThemeFullPath = []; - foreach ($ancestors as $ancestor) { - $ancestorThemeFullPath[] = $ancestor->getFullPath(); - } - return $ancestorThemeFullPath; - } - - /** - * Verbose log - * - * @param string $message - * @return void - */ - private function verboseLog($message) - { - if ($this->output->isVerbose()) { - $this->output->writeln($message); - } } } diff --git a/app/code/Magento/Deploy/Model/Filesystem.php b/app/code/Magento/Deploy/Model/Filesystem.php index 6555267766f5d..e0ef097ba0d70 100644 --- a/app/code/Magento/Deploy/Model/Filesystem.php +++ b/app/code/Magento/Deploy/Model/Filesystem.php @@ -1,6 +1,6 @@ pid = 0; + $this->status = null; + $this->handler = $handler; + } + + /** + * @return int + */ + public function getPid() + { + return $this->pid; + } + + /** + * @param int $pid + * @return void + */ + public function setPid($pid) + { + $this->pid = $pid; + } + + /** + * @return void + * @SuppressWarnings(PHPMD.ExitExpression) + */ + public function run() + { + $status = call_user_func($this->handler, $this); + + $status = is_integer($status) ? $status : 0; + exit($status); + } + + /** + * @return bool + */ + public function isCompleted() + { + $pid = pcntl_waitpid($this->getPid(), $status, WNOHANG); + if ($pid == -1 || $pid === $this->getPid()) { + $this->status = pcntl_wexitstatus($status); + return true; + } + return false; + } + + /** + * @return int|null + */ + public function getStatus() + { + return $this->status; + } +} diff --git a/app/code/Magento/Deploy/Model/ProcessManager.php b/app/code/Magento/Deploy/Model/ProcessManager.php new file mode 100644 index 0000000000000..7715d0db2be54 --- /dev/null +++ b/app/code/Magento/Deploy/Model/ProcessManager.php @@ -0,0 +1,107 @@ +processFactory = $processFactory; + } + + /** + * Forks the currently running process. + * + * @param callable $handler + * + * @return Process + * @throws \RuntimeException + * @SuppressWarnings(PHPMD.ExitExpression) + */ + public function fork(callable $handler) + { + $process = $this->createProcess($handler); + $pid = pcntl_fork(); + + if ($pid === -1) { + throw new \RuntimeException('Unable to fork a new process'); + } + + if ($pid) { + $process->setPid($pid); + $this->processes[$pid] = $process; + return $process; + } + + // process child process + $this->processes = []; + $process->setPid(getmypid()); + $process->run(); + + exit(0); + } + + /** + * @return Process[] + */ + public function getProcesses() + { + return $this->processes; + } + + /** + * @param Process $process + * @return void + */ + public function delete(Process $process) + { + unset($this->processes[$process->getPid()]); + } + + /** + * @param callable $handler + * @return Process + */ + private function createProcess(callable $handler) + { + return $this->processFactory->create(['handler' => $handler]); + } + + /** + * Protect against zombie process + * @return void + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + private function freeResources() + { + foreach ($this->processes as $process) { + if (pcntl_waitpid($process->getPid(), $status) === -1) { + throw new \RuntimeException('Error while waiting for process '. $process->getPid()); + } + } + } + + /** + * Free resources + */ + public function __destruct() + { + $this->freeResources(); + } +} diff --git a/app/code/Magento/Deploy/Model/ProcessQueueManager.php b/app/code/Magento/Deploy/Model/ProcessQueueManager.php new file mode 100644 index 0000000000000..e5b2dd34108b3 --- /dev/null +++ b/app/code/Magento/Deploy/Model/ProcessQueueManager.php @@ -0,0 +1,160 @@ +processManager = $processManager; + $this->resourceConnection = $resourceConnection; + $this->processTaskFactory = $processTaskFactory; + $this->maxProcesses = $maxProcesses; + } + + /** + * @param callable $task + * @param callable[] $dependentTasks + * @return void + */ + public function addTaskToQueue(callable $task, $dependentTasks = []) + { + $dependentTasks = array_map(function (callable $task) { + return $this->createTask($task); + }, $dependentTasks); + + $task = $this->createTask($task, $dependentTasks); + $this->tasksQueue[$task->getId()] = $task; + } + + /** + * Process tasks queue + * @return int + */ + public function process() + { + $processQueue = []; + $this->internalQueueProcess($this->tasksQueue, $processQueue); + + $returnStatus = 0; + while (count($this->processManager->getProcesses()) > 0) { + foreach ($this->processManager->getProcesses() as $process) { + if ($process->isCompleted()) { + $dependedTasks = isset($this->processTaskMap[$process->getPid()]) + ? $this->processTaskMap[$process->getPid()] + : []; + + $this->processManager->delete($process); + $returnStatus |= $process->getStatus(); + + $this->internalQueueProcess(array_merge($processQueue, $dependedTasks), $processQueue); + + if (count($this->processManager->getProcesses()) >= $this->maxProcesses) { + break 1; + } + } + } + usleep(5000); + } + $this->resourceConnection->closeConnection(); + + return $returnStatus; + } + + /** + * @param ProcessTask[] $taskQueue + * @param ProcessTask[] $processQueue + * @return void + */ + private function internalQueueProcess($taskQueue, &$processQueue) + { + $processNumber = count($this->processManager->getProcesses()); + foreach ($taskQueue as $task) { + if ($processNumber >= $this->maxProcesses) { + if (!isset($processQueue[$task->getId()])) { + $processQueue[$task->getId()] = $task; + } + } else { + unset($processQueue[$task->getId()]); + $this->fork($task); + $processNumber++; + } + } + } + + /** + * @param callable $handler + * @param array $dependentTasks + * @return ProcessTask + */ + private function createTask($handler, $dependentTasks = []) + { + return $this->processTaskFactory->create(['handler' => $handler, 'dependentTasks' => $dependentTasks]); + } + + /** + * @param ProcessTask $task + * @return void + */ + private function fork(ProcessTask $task) + { + $process = $this->processManager->fork($task->getHandler()); + if ($task->getDependentTasks()) { + $pid = $process->getPid(); + foreach ($task->getDependentTasks() as $dependentTask) { + $this->processTaskMap[$pid][$dependentTask->getId()] = $dependentTask; + } + } + } +} diff --git a/app/code/Magento/Deploy/Model/ProcessTask.php b/app/code/Magento/Deploy/Model/ProcessTask.php new file mode 100644 index 0000000000000..bba6b03cf3900 --- /dev/null +++ b/app/code/Magento/Deploy/Model/ProcessTask.php @@ -0,0 +1,60 @@ +taskId = uniqid('', true); + $this->handler = $handler; + $this->dependentTasks = $dependentTasks; + } + + /** + * @return callable + */ + public function getHandler() + { + return $this->handler; + } + + /** + * @return string + */ + public function getId() + { + return $this->taskId; + } + + /** + * @return ProcessTask[] + */ + public function getDependentTasks() + { + return $this->dependentTasks; + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/ApplicationDumpCommandTest.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/ApplicationDumpCommandTest.php new file mode 100644 index 0000000000000..c12c857c6c2c9 --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/ApplicationDumpCommandTest.php @@ -0,0 +1,91 @@ +input = $this->getMockBuilder(InputInterface::class) + ->getMockForAbstractClass(); + $this->output = $this->getMockBuilder(OutputInterface::class) + ->getMockForAbstractClass(); + $this->writer = $this->getMockBuilder(Writer::class) + ->disableOriginalConstructor() + ->getMock(); + $this->source = $this->getMockBuilder(SourceInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->command = new ApplicationDumpCommand($this->writer, [[ + 'namespace' => 'system', + 'source' => $this->source + ]]); + } + + public function testExport() + { + $dump = [ + 'system' => ['systemDATA'] + ]; + $data = [ConfigFilePool::APP_CONFIG => $dump]; + $this->source + ->expects($this->once()) + ->method('get') + ->willReturn(['systemDATA']); + $this->output->expects($this->once()) + ->method('writeln') + ->with('Done.'); + $this->writer->expects($this->once()) + ->method('saveConfig') + ->with($data); + $method = new \ReflectionMethod(ApplicationDumpCommand::class, 'execute'); + $method->setAccessible(true); + $this->assertEquals( + Cli::RETURN_SUCCESS, + $method->invokeArgs( + $this->command, + [$this->input, $this->output] + ) + ); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/DeployStaticContentCommandTest.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/DeployStaticContentCommandTest.php index 6bd8f79cb2f90..644fb86768b73 100644 --- a/app/code/Magento/Deploy/Test/Unit/Console/Command/DeployStaticContentCommandTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/DeployStaticContentCommandTest.php @@ -1,6 +1,6 @@ objectManager = $this->getMockForAbstractClass('Magento\Framework\ObjectManagerInterface'); - $this->objectManagerFactory = $this->getMock('Magento\Framework\App\ObjectManagerFactory', [], [], '', false); - $this->deployer = $this->getMock('Magento\Deploy\Model\Deployer', [], [], '', false); - $this->filesUtil = $this->getMock('Magento\Framework\App\Utility\Files', [], [], '', false); - $this->validator = $this->getMock('Magento\Framework\Validator\Locale', [], [], '', false); - $this->command = new DeployStaticContentCommand( - $this->objectManagerFactory, - $this->validator, - $this->objectManager + $this->objectManager = $this->getMockForAbstractClass(\Magento\Framework\ObjectManagerInterface::class); + $this->objectManagerFactory = $this->getMock( + \Magento\Framework\App\ObjectManagerFactory::class, + [], + [], + '', + false ); + $this->deployer = $this->getMock(\Magento\Deploy\Model\DeployManager::class, [], [], '', false); + $this->filesUtil = $this->getMock(\Magento\Framework\App\Utility\Files::class, [], [], '', false); + + $this->validator = $this->getMock(\Magento\Framework\Validator\Locale::class, [], [], '', false); + $this->command = (new ObjectManager($this))->getObject(DeployStaticContentCommand::class, [ + 'objectManagerFactory' => $this->objectManagerFactory, + 'validator' => $this->validator, + 'objectManager' => $this->objectManager, + ]); } public function testExecute() { + $this->filesUtil->expects(self::any())->method('getStaticPreProcessingFiles')->willReturn([]); $this->deployer->expects($this->once())->method('deploy'); + $this->objectManager->expects($this->at(0))->method('create')->willReturn($this->filesUtil); + $this->objectManager->expects($this->at(1))->method('create')->willReturn($this->deployer); - $this->objectManager->expects($this->at(0)) - ->method('create') - ->willReturn($this->filesUtil); + $tester = new CommandTester($this->command); + $tester->execute([]); + } - $this->objectManager->expects($this->at(1)) - ->method('create') - ->willReturn($this->deployer); + public function testExecuteValidateLanguages() + { + $this->filesUtil->expects(self::any())->method('getStaticPreProcessingFiles')->willReturn([]); + $this->deployer->expects($this->once())->method('deploy'); + $this->objectManager->expects($this->at(0))->method('create')->willReturn($this->filesUtil); + $this->objectManager->expects($this->at(1))->method('create')->willReturn($this->deployer); + $this->validator->expects(self::exactly(2))->method('isValid')->willReturnMap([ + ['en_US', true], + ['uk_UA', true], + ]); - $this->validator->expects($this->once())->method('isValid')->with('en_US')->willReturn(true); + $tester = new CommandTester($this->command); + $tester->execute(['languages' => ['en_US', 'uk_UA']]); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage --language (-l) and --exclude-language cannot be used at the same tim + */ + public function testExecuteIncludedExcludedLanguages() + { + $this->filesUtil->expects(self::any())->method('getStaticPreProcessingFiles')->willReturn([]); + $this->objectManager->expects($this->at(0))->method('create')->willReturn($this->filesUtil); + $this->validator->expects(self::exactly(2))->method('isValid')->willReturnMap([ + ['en_US', true], + ['uk_UA', true], + ]); $tester = new CommandTester($this->command); - $tester->execute([]); + $tester->execute(['--language' => ['en_US', 'uk_UA'], '--exclude-language' => 'ru_RU']); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage --area (-a) and --exclude-area cannot be used at the same tim + */ + public function testExecuteIncludedExcludedAreas() + { + $this->filesUtil->expects(self::any())->method('getStaticPreProcessingFiles')->willReturn([]); + $this->objectManager->expects($this->at(0))->method('create')->willReturn($this->filesUtil); + + $tester = new CommandTester($this->command); + $tester->execute(['--area' => ['a1', 'a2'], '--exclude-area' => 'a3']); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage --theme (-t) and --exclude-theme cannot be used at the same tim + */ + public function testExecuteIncludedExcludedThemes() + { + $this->filesUtil->expects(self::any())->method('getStaticPreProcessingFiles')->willReturn([]); + $this->objectManager->expects($this->at(0))->method('create')->willReturn($this->filesUtil); + + $tester = new CommandTester($this->command); + $tester->execute(['--theme' => ['t1', 't2'], '--exclude-theme' => 't3']); } /** @@ -79,6 +140,10 @@ public function testExecute() */ public function testExecuteInvalidLanguageArgument() { + $this->filesUtil->expects(self::any())->method('getStaticPreProcessingFiles')->willReturn([]); + $this->objectManager->expects($this->at(0)) + ->method('create') + ->willReturn($this->filesUtil); $wrongParam = ['languages' => ['ARG_IS_WRONG']]; $commandTester = new CommandTester($this->command); $commandTester->execute($wrongParam); diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/FunctionExistMock.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/FunctionExistMock.php new file mode 100644 index 0000000000000..2441570213e43 --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/FunctionExistMock.php @@ -0,0 +1,16 @@ +area = 'adminhtml'; + $this->themePath = '/theme/path'; + $this->locale = 'en_US'; + + $outputMock = $this->getMock(OutputInterface::class, [], [], '', false); + $jsTranslationMock = $this->getMock(Config::class, [], [], '', false); + $jsTranslationMock->expects($this->once())->method('dictionaryEnabled')->willReturn(false); + $minificationMock = $this->getMock(Minification::class, [], [], '', false); + $minificationMock->expects($this->once())->method('isEnabled')->with('js')->willReturn(true); + + $themeMock = $this->getMockBuilder(\Magento\Framework\View\Design\ThemeInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $designMock = $this->getMock(\Magento\Framework\View\DesignInterface::class, [], [], '', false); + $designMock->expects($this->once())->method('setDesignTheme')->with($themeMock, $this->area)->willReturnSelf(); + $assetRepoMock = $this->getMock(Repository::class, [], [], '', false); + $assetRepoFactoryMock = $this->getMock(RepositoryFactory::class, ['create'], [], '', false); + $assetRepoFactoryMock->expects($this->once()) + ->method('create') + ->with(['design' => $designMock]) + ->willReturn($assetRepoMock); + + $fileManagerMock = $this->getMock(\Magento\RequireJs\Model\FileManager::class, [], [], '', false); + $fileManagerMock->expects($this->once())->method('createRequireJsConfigAsset')->willReturnSelf(); + $fileManagerMock->expects($this->once())->method('createMinResolverAsset')->willReturnSelf(); + $fileManagerFactoryMock = $this->getMock(FileManagerFactory::class, ['create'], [], '', false); + $fileManagerFactoryMock->expects($this->once())->method('create')->willReturn($fileManagerMock); + + $requireJsConfigMock = $this->getMock(\Magento\Framework\RequireJs\Config::class, [], [], '', false); + $configFactoryMock = $this->getMock(ConfigFactory::class, ['create'], [], '', false); + $configFactoryMock->expects($this->once())->method('create')->willReturn($requireJsConfigMock); + + $assetPublisherMock = $this->getMock(Publisher::class, [], [], '', false); + + $bundleManagerMock = $this->getMock(Manager::class, [], [], '', false); + $bundleManagerMock->expects($this->once())->method('flush'); + + $themeProviderMock = $this->getMock(ThemeProviderInterface::class, [], [], '', false); + $loggerMock = $this->getMock(LoggerInterface::class, [], [], '', false); + + $filesUtilMock = $this->getMock(Files::class, [], [], '', false); + $filesUtilMock->expects($this->once())->method('getStaticPreProcessingFiles')->willReturn([]); + $filesUtilMock->expects($this->once())->method('getStaticLibraryFiles')->willReturn([]); + + $designFactoryMock = $this->getMock(DesignInterfaceFactory::class, ['create'], [], '', false); + $designFactoryMock->expects($this->once())->method('create')->willReturn($designMock); + + $localeResolverMock = $this->getMock(ResolverInterface::class, [], [], '', false); + $localeResolverMock->expects($this->once())->method('setLocale')->with($this->locale); + + $themeList = $this->getMock(ListInterface::class, [], [], '', false); + $themeList->expects($this->once())->method('getThemeByFullPath') + ->with($this->area . '/' . $this->themePath) + ->willReturn($themeMock); + + $this->model = new LocaleDeploy( + $outputMock, + $jsTranslationMock, + $minificationMock, + $assetRepoMock, + $assetRepoFactoryMock, + $fileManagerFactoryMock, + $configFactoryMock, + $assetPublisherMock, + $bundleManagerMock, + $themeProviderMock, + $loggerMock, + $filesUtilMock, + $designFactoryMock, + $localeResolverMock, + [], + [\Magento\Deploy\Console\Command\DeployStaticOptionsInterface::NO_JAVASCRIPT => 0] + ); + $property = new \ReflectionProperty(get_class($this->model), 'themeList'); + $property->setAccessible(true); + $property->setValue($this->model, $themeList); + } + + public function testDeploy() + { + $this->assertEquals( + \Magento\Framework\Console\Cli::RETURN_SUCCESS, + $this->model->deploy($this->area, $this->themePath, $this->locale) + ); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Model/Deploy/LocaleQuickDeployTest.php b/app/code/Magento/Deploy/Test/Unit/Model/Deploy/LocaleQuickDeployTest.php new file mode 100644 index 0000000000000..6c693fe5f3d85 --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Model/Deploy/LocaleQuickDeployTest.php @@ -0,0 +1,114 @@ +outputMock = $this->getMockBuilder(OutputInterface::class) + ->setMethods(['writeln']) + ->getMockForAbstractClass(); + + $this->staticDirectoryMock = $this->getMockBuilder(WriteInterface::class) + ->setMethods(['createSymlink', 'getAbsolutePath', 'getRelativePath', 'copyFile', 'readRecursively']) + ->getMockForAbstractClass(); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Deploy base locale must be set for Quick Deploy + */ + public function testDeployWithoutBaseLocale() + { + $this->getModel()->deploy('adminhtml', 'Magento/backend', 'en_US'); + } + + public function testDeployWithSymlinkStrategy() + { + $area = 'adminhtml'; + $themePath = 'Magento/backend'; + $locale = 'uk_UA'; + $baseLocal = 'en_US'; + + $this->staticDirectoryMock->expects(self::exactly(2)) + ->method('createSymlink') + ->withConsecutive( + ['adminhtml/Magento/backend/en_US', 'adminhtml/Magento/backend/uk_UA'], + ['_requirejs/adminhtml/Magento/backend/en_US', '_requirejs/adminhtml/Magento/backend/uk_UA'] + ); + + $model = $this->getModel([ + DeployInterface::DEPLOY_BASE_LOCALE => $baseLocal, + Options::SYMLINK_LOCALE => 1, + ]); + $model->deploy($area, $themePath, $locale); + } + + public function testDeployWithCopyStrategy() + { + + $area = 'adminhtml'; + $themePath = 'Magento/backend'; + $locale = 'uk_UA'; + $baseLocal = 'en_US'; + + $this->staticDirectoryMock->expects(self::never())->method('createSymlink'); + $this->staticDirectoryMock->expects(self::exactly(2))->method('readRecursively')->willReturnMap([ + ['adminhtml/Magento/backend/en_US', [$baseLocal . 'file1', $baseLocal . 'dir']], + [RequireJsConfig::DIR_NAME . '/adminhtml/Magento/backend/en_US', [$baseLocal . 'file2']] + ]); + $this->staticDirectoryMock->expects(self::exactly(3))->method('isFile')->willReturnMap([ + [$baseLocal . 'file1', true], + [$baseLocal . 'dir', false], + [$baseLocal . 'file2', true], + ]); + $this->staticDirectoryMock->expects(self::exactly(2))->method('copyFile')->withConsecutive( + [$baseLocal . 'file1', $locale . 'file1', null], + [$baseLocal . 'file2', $locale . 'file2', null] + ); + + $model = $this->getModel([ + DeployInterface::DEPLOY_BASE_LOCALE => $baseLocal, + Options::SYMLINK_LOCALE => 0, + ]); + $model->deploy($area, $themePath, $locale); + } + + /** + * @param array $options + * @return LocaleQuickDeploy + */ + private function getModel($options = []) + { + return (new ObjectManager($this))->getObject( + LocaleQuickDeploy::class, + [ + 'output' => $this->outputMock, + 'staticDirectory' => $this->staticDirectoryMock, + 'options' => $options + ] + ); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Model/Deploy/TemplateMinifierTest.php b/app/code/Magento/Deploy/Test/Unit/Model/Deploy/TemplateMinifierTest.php new file mode 100644 index 0000000000000..594f1ec5cd93c --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Model/Deploy/TemplateMinifierTest.php @@ -0,0 +1,56 @@ +minifierMock = $this->getMock( + \Magento\Framework\View\Template\Html\MinifierInterface::class, + [], + [], + '', + false + ); + $this->filesUtilsMock = $this->getMock(\Magento\Framework\App\Utility\Files::class, [], [], '', false); + + $this->model = new \Magento\Deploy\Model\Deploy\TemplateMinifier( + $this->filesUtilsMock, + $this->minifierMock + ); + } + + public function testMinifyTemplates() + { + $templateMock = "template.phtml"; + $templatesMock = [$templateMock]; + + $this->filesUtilsMock->expects($this->once())->method('getPhtmlFiles')->with(false, false) + ->willReturn($templatesMock); + $this->minifierMock->expects($this->once())->method('minify')->with($templateMock); + + self::assertEquals(1, $this->model->minifyTemplates()); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Model/DeployManagerTest.php b/app/code/Magento/Deploy/Test/Unit/Model/DeployManagerTest.php new file mode 100644 index 0000000000000..95c9221ccbc44 --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Model/DeployManagerTest.php @@ -0,0 +1,168 @@ +deployStrategyProviderFactoryMock = $this->getMock( + \Magento\Deploy\Model\DeployStrategyProviderFactory::class, + ['create'], + [], + '', + false + ); + $this->versionStorageMock = $this->getMock( + \Magento\Framework\App\View\Deployment\Version\StorageInterface::class, + [], + [], + '', + false + ); + $this->minifierTemplateMock = $this->getMock( + \Magento\Deploy\Model\Deploy\TemplateMinifier::class, + [], + [], + '', + false + ); + $this->processQueueManagerFactoryMock = $this->getMock( + \Magento\Deploy\Model\ProcessQueueManagerFactory::class, + [], + [], + '', + false + ); + $this->stateMock = $this->getMockBuilder(\Magento\Framework\App\State::class) + ->disableOriginalConstructor() + ->getMock(); + $this->outputMock = $this->getMock(\Symfony\Component\Console\Output\OutputInterface::class, [], [], '', false); + } + + public function testSaveDeployedVersion() + { + $version = (new \DateTime())->getTimestamp(); + $this->outputMock->expects($this->once())->method('writeln')->with("New version of deployed files: {$version}"); + $this->versionStorageMock->expects($this->once())->method('save')->with($version); + + $this->assertEquals( + \Magento\Framework\Console\Cli::RETURN_SUCCESS, + $this->getModel([Options::NO_HTML_MINIFY => true])->deploy() + ); + } + + public function testSaveDeployedVersionDryRun() + { + $options = [Options::DRY_RUN => true, Options::NO_HTML_MINIFY => true]; + + $this->outputMock->expects(self::once())->method('writeln')->with( + 'Dry run. Nothing will be recorded to the target directory.' + ); + $this->versionStorageMock->expects($this->never())->method('save'); + + $this->getModel($options)->deploy(); + } + + public function testMinifyTemplates() + { + $this->minifierTemplateMock->expects($this->once())->method('minifyTemplates')->willReturn(2); + $this->outputMock->expects($this->atLeastOnce())->method('writeln')->withConsecutive( + ["=== Minify templates ==="], + ["\nSuccessful: 2 files modified\n---\n"] + ); + + $this->getModel([Options::NO_HTML_MINIFY => false])->deploy(); + } + + public function testMinifyTemplatesNoHtmlMinify() + { + $version = (new \DateTime())->getTimestamp(); + $this->outputMock->expects($this->once())->method('writeln')->with("New version of deployed files: {$version}"); + $this->versionStorageMock->expects($this->once())->method('save')->with($version); + + $this->getModel([Options::NO_HTML_MINIFY => true])->deploy(); + } + + public function testDeploy() + { + $area = 'frontend'; + $themePath = 'themepath'; + $locale = 'en_US'; + $options = [Options::NO_HTML_MINIFY => true]; + $strategyProviderMock = $this->getMock(\Magento\Deploy\Model\DeployStrategyProvider::class, [], [], '', false); + $deployStrategyMock = $this->getMock(\Magento\Deploy\Model\Deploy\DeployInterface::class, [], [], '', false); + + $model = $this->getModel($options); + $model->addPack($area, $themePath, $locale); + $this->deployStrategyProviderFactoryMock->expects($this->once())->method('create')->with( + ['output' => $this->outputMock, 'options' => $options] + )->willReturn($strategyProviderMock); + $strategyProviderMock->expects($this->once())->method('getDeployStrategies')->with($area, $themePath, [$locale]) + ->willReturn([$locale => $deployStrategyMock]); + $this->stateMock->expects(self::once())->method('emulateAreaCode') + ->with($area, [$deployStrategyMock, 'deploy'], [$area, $themePath, $locale]) + ->willReturn(\Magento\Framework\Console\Cli::RETURN_SUCCESS); + + $version = (new \DateTime())->getTimestamp(); + $this->outputMock->expects(self::once())->method('writeln')->with("New version of deployed files: {$version}"); + $this->versionStorageMock->expects($this->once())->method('save')->with($version); + + $this->assertEquals(\Magento\Framework\Console\Cli::RETURN_SUCCESS, $model->deploy()); + } + + /** + * @param array $options + * @return \Magento\Deploy\Model\DeployManager + */ + private function getModel(array $options) + { + return new \Magento\Deploy\Model\DeployManager( + $this->outputMock, + $this->versionStorageMock, + $this->deployStrategyProviderFactoryMock, + $this->processQueueManagerFactoryMock, + $this->minifierTemplateMock, + $this->stateMock, + $options + ); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Model/DeployStrategyFactoryTest.php b/app/code/Magento/Deploy/Test/Unit/Model/DeployStrategyFactoryTest.php new file mode 100644 index 0000000000000..56ff3665720ec --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Model/DeployStrategyFactoryTest.php @@ -0,0 +1,53 @@ +objectManagerMock = $this->getMock(ObjectManagerInterface::class); + + $this->unit = (new ObjectManager($this))->getObject( + DeployStrategyFactory::class, + [ + 'objectManager' => $this->objectManagerMock, + ] + ); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Wrong deploy strategy type: wrong-type + */ + public function testCreateWithWrongStrategyType() + { + $this->unit->create('wrong-type'); + } + + public function testCreate() + { + $this->objectManagerMock->expects(self::once())->method('create') + ->with(LocaleDeploy::class, ['arg1' => 1]); + + $this->unit->create(DeployStrategyFactory::DEPLOY_STRATEGY_STANDARD, ['arg1' => 1]); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php b/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php index 9268fedd320be..c17714b54d61d 100644 --- a/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Model/FilesystemTest.php @@ -1,6 +1,6 @@ processManagerMock = $this->getMock(ProcessManager::class, [], [], '', false); + $this->resourceConnectionMock = $this->getMock(ResourceConnection::class, [], [], '', false); + $this->processTaskFactoryMock = $this->getMock(ProcessTaskFactory::class, ['create'], [], '', false); + $this->processTaskMock = $this->getMock(ProcessTask::class, [], [], '', false); + $this->processTaskFactoryMock->expects($this->any())->method('create')->willReturn($this->processTaskMock); + $this->model = (new ObjectManager($this))->getObject( + \Magento\Deploy\Model\ProcessQueueManager::class, + [ + 'processManager' => $this->processManagerMock, + 'resourceConnection' => $this->resourceConnectionMock, + 'processTaskFactory' => $this->processTaskFactoryMock + ] + ); + } + + public function testProcess() + { + $callableMock = function () { + return true; + }; + $this->processTaskMock->expects($this->any())->method('getHandler')->willReturn($callableMock); + + $processMock = $this->getMock(\Magento\Deploy\Model\Process::class, [], [], '', false); + + $this->model->addTaskToQueue($callableMock, []); + $this->processManagerMock->expects($this->atLeastOnce())->method('getProcesses')->willReturnOnConsecutiveCalls( + [$processMock], + [$processMock], + [$processMock], + [$processMock], + [$processMock], + [] + ); + $processMock->expects($this->once())->method('isCompleted')->willReturn(true); + $processMock->expects($this->atLeastOnce())->method('getPid')->willReturn(42); + $processMock->expects($this->once())->method('getStatus')->willReturn(0); + $this->processManagerMock->expects($this->once())->method('delete')->with($processMock); + + $this->resourceConnectionMock->expects(self::once())->method('closeConnection'); + + $this->assertEquals(0, $this->model->process()); + } +} diff --git a/app/code/Magento/Deploy/cli_commands.php b/app/code/Magento/Deploy/cli_commands.php new file mode 100644 index 0000000000000..d966273bc6c86 --- /dev/null +++ b/app/code/Magento/Deploy/cli_commands.php @@ -0,0 +1,9 @@ + @@ -13,12 +13,20 @@ + + + + AlternativeSourceProcessors + + + Magento\Deploy\Console\Command\DeployStaticContentCommand Magento\Deploy\Console\Command\SetModeCommand Magento\Deploy\Console\Command\ShowModeCommand + \Magento\Deploy\Console\Command\App\ApplicationDumpCommand diff --git a/app/code/Magento/Deploy/etc/module.xml b/app/code/Magento/Deploy/etc/module.xml index aa7e755178ccd..9197c17ef0931 100644 --- a/app/code/Magento/Deploy/etc/module.xml +++ b/app/code/Magento/Deploy/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Deploy/registration.php b/app/code/Magento/Deploy/registration.php index b692eb97c29d8..eda7bc5ea47a5 100644 --- a/app/code/Magento/Deploy/registration.php +++ b/app/code/Magento/Deploy/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Developer/Test/Unit/Helper/DataTest.php b/app/code/Magento/Developer/Test/Unit/Helper/DataTest.php index a802fe2200411..5146a54b91931 100644 --- a/app/code/Magento/Developer/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Developer/Test/Unit/Helper/DataTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Developer/etc/adminhtml/system.xml b/app/code/Magento/Developer/etc/adminhtml/system.xml index 551704598ee70..6e3916afac3c8 100644 --- a/app/code/Magento/Developer/etc/adminhtml/system.xml +++ b/app/code/Magento/Developer/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Developer/etc/config.xml b/app/code/Magento/Developer/etc/config.xml index a39cd241fe63d..4bdd425bca51f 100644 --- a/app/code/Magento/Developer/etc/config.xml +++ b/app/code/Magento/Developer/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Developer/etc/di.xml b/app/code/Magento/Developer/etc/di.xml index a7fc549a0d993..df907125d733b 100644 --- a/app/code/Magento/Developer/etc/di.xml +++ b/app/code/Magento/Developer/etc/di.xml @@ -1,7 +1,7 @@ @@ -241,4 +241,12 @@ web + + + + + 1 + + + diff --git a/app/code/Magento/Developer/etc/frontend/di.xml b/app/code/Magento/Developer/etc/frontend/di.xml index 23be59086b84e..6d526d8d02fc5 100644 --- a/app/code/Magento/Developer/etc/frontend/di.xml +++ b/app/code/Magento/Developer/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Developer/etc/module.xml b/app/code/Magento/Developer/etc/module.xml index 1a24a918b9b81..cc609870d3c76 100644 --- a/app/code/Magento/Developer/etc/module.xml +++ b/app/code/Magento/Developer/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Developer/registration.php b/app/code/Magento/Developer/registration.php index 95ae8d00e3ec4..5b0bab4b1d463 100644 --- a/app/code/Magento/Developer/registration.php +++ b/app/code/Magento/Developer/registration.php @@ -1,6 +1,6 @@ @@ -1557,4 +1557,4 @@ CM Zimbabwe - \ No newline at end of file + diff --git a/app/code/Magento/Dhl/Test/Unit/Model/_files/rates_request_data_dhl.php b/app/code/Magento/Dhl/Test/Unit/Model/_files/rates_request_data_dhl.php index 78e6dddb8c8eb..cbe3cf6b9f59b 100644 --- a/app/code/Magento/Dhl/Test/Unit/Model/_files/rates_request_data_dhl.php +++ b/app/code/Magento/Dhl/Test/Unit/Model/_files/rates_request_data_dhl.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Dhl/Test/Unit/Model/_files/success_dhl_response_rates.xml b/app/code/Magento/Dhl/Test/Unit/Model/_files/success_dhl_response_rates.xml index ac3a29e4a2e6d..1f8635a8b97a1 100644 --- a/app/code/Magento/Dhl/Test/Unit/Model/_files/success_dhl_response_rates.xml +++ b/app/code/Magento/Dhl/Test/Unit/Model/_files/success_dhl_response_rates.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Dhl/composer.json b/app/code/Magento/Dhl/composer.json index 038fdc5cf37e3..c636c41f0c479 100644 --- a/app/code/Magento/Dhl/composer.json +++ b/app/code/Magento/Dhl/composer.json @@ -2,7 +2,7 @@ "name": "magento/module-dhl", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/module-config": "100.1.*", "magento/module-store": "100.1.*", "magento/module-shipping": "100.1.*", @@ -19,7 +19,7 @@ "magento/module-checkout": "100.1.*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Dhl/etc/adminhtml/system.xml b/app/code/Magento/Dhl/etc/adminhtml/system.xml index 4f28555021d99..dbbfe2a9ff415 100644 --- a/app/code/Magento/Dhl/etc/adminhtml/system.xml +++ b/app/code/Magento/Dhl/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Dhl/etc/config.xml b/app/code/Magento/Dhl/etc/config.xml index 5f094005afa2b..416c6ab271e0b 100644 --- a/app/code/Magento/Dhl/etc/config.xml +++ b/app/code/Magento/Dhl/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Dhl/etc/countries.xml b/app/code/Magento/Dhl/etc/countries.xml index 6402094f08dee..1b795fe8aad0b 100644 --- a/app/code/Magento/Dhl/etc/countries.xml +++ b/app/code/Magento/Dhl/etc/countries.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Dhl/etc/di.xml b/app/code/Magento/Dhl/etc/di.xml index 25b90ce8850d8..901d45b212f40 100644 --- a/app/code/Magento/Dhl/etc/di.xml +++ b/app/code/Magento/Dhl/etc/di.xml @@ -1,7 +1,7 @@ @@ -13,4 +13,13 @@ + + + + 1 + 1 + 1 + + + diff --git a/app/code/Magento/Dhl/etc/module.xml b/app/code/Magento/Dhl/etc/module.xml index eccbdf0a0c19c..9e3feb6517b5a 100644 --- a/app/code/Magento/Dhl/etc/module.xml +++ b/app/code/Magento/Dhl/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Dhl/registration.php b/app/code/Magento/Dhl/registration.php index 4bafb33380909..0463140f1263a 100644 --- a/app/code/Magento/Dhl/registration.php +++ b/app/code/Magento/Dhl/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Dhl/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Dhl/view/frontend/layout/checkout_index_index.xml index df08f1b1234fe..5fc507914bce9 100644 --- a/app/code/Magento/Dhl/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Dhl/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js index 016a689d5d436..6752f87f5272e 100644 --- a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js +++ b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global define*/ @@ -16,6 +16,9 @@ define( }, 'country_id': { 'required': true + }, + 'city': { + 'required': true } }; } diff --git a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js index e41297ad6906c..f193cb77b8875 100644 --- a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js +++ b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global define*/ diff --git a/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js index 317c09864e68f..3133ba351541b 100644 --- a/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js +++ b/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ diff --git a/app/code/Magento/Directory/Api/CountryInformationAcquirerInterface.php b/app/code/Magento/Directory/Api/CountryInformationAcquirerInterface.php index 67c40e149839a..b8790fad2d23d 100644 --- a/app/code/Magento/Directory/Api/CountryInformationAcquirerInterface.php +++ b/app/code/Magento/Directory/Api/CountryInformationAcquirerInterface.php @@ -1,6 +1,6 @@ scopeConfig = $scopeConfig; + $this->storeManager = $storeManager; + } + + /** + * Retrieve all allowed countries for scope or scopes + * + * @param string | null $scopeCode + * @param string $scope + * @return array + */ + public function getAllowedCountries( + $scope = ScopeInterface::SCOPE_WEBSITE, + $scopeCode = null + ) { + if (empty($scopeCode)) { + $scopeCode = $this->getDefaultScopeCode($scope); + } + + switch ($scope) { + case ScopeInterface::SCOPE_WEBSITES: + case ScopeInterface::SCOPE_STORES: + $allowedCountries = []; + foreach ($scopeCode as $singleFilter) { + $allowedCountries = array_merge( + $allowedCountries, + $this->getCountriesFromConfig($this->getSingleScope($scope), $singleFilter) + ); + } + break; + default: + $allowedCountries = $this->getCountriesFromConfig($scope, $scopeCode); + } + + return $this->makeCountriesUnique($allowedCountries); + } + + /** + * Resolve scope code by scope + * + * @throws \InvalidArgumentException + * @param string $scope + * @return array|int + */ + private function getDefaultScopeCode($scope) + { + switch ($scope) { + case ScopeInterface::SCOPE_WEBSITE: + return $this->storeManager->getWebsite()->getId(); + case ScopeInterface::SCOPE_STORE: + return $this->storeManager->getStore()->getId(); + case ScopeInterface::SCOPE_GROUP: + return $this->storeManager->getGroup()->getId(); + case ScopeInterface::SCOPE_WEBSITES: + return [$this->storeManager->getWebsite()->getId()]; + case ScopeInterface::SCOPE_STORES: + return [$this->storeManager->getStore()->getId()]; + default: + throw new \InvalidArgumentException("Invalid scope is specified"); + } + } + + /** + * Return Unique Countries by merging them by keys + * + * @param array $allowedCountries + * @return array + */ + public function makeCountriesUnique(array $allowedCountries) + { + return array_combine($allowedCountries, $allowedCountries); + } + + /** + * Takes countries from Countries Config data + * + * @param string $scope + * @param int $scopeCode + * @return array + */ + public function getCountriesFromConfig($scope, $scopeCode) + { + return explode( + ',', + (string) $this->scopeConfig->getValue( + self::ALLOWED_COUNTRIES_PATH, + $scope, + $scopeCode + ) + ); + } + + /** + * Return Single Scope + * + * @param string $scope + * @return string + */ + private function getSingleScope($scope) + { + if ($scope == ScopeInterface::SCOPE_WEBSITES) { + return ScopeInterface::SCOPE_WEBSITE; + } + + if ($scope == ScopeInterface::SCOPE_STORES) { + return ScopeInterface::SCOPE_STORE; + } + + return $scope; + } +} diff --git a/app/code/Magento/Directory/Model/Config/Source/Allregion.php b/app/code/Magento/Directory/Model/Config/Source/Allregion.php index 6da89878826d9..40b0bbc51a1aa 100644 --- a/app/code/Magento/Directory/Model/Config/Source/Allregion.php +++ b/app/code/Magento/Directory/Model/Config/Source/Allregion.php @@ -1,6 +1,6 @@ _init('Magento\Directory\Model\Country', 'Magento\Directory\Model\ResourceModel\Country'); } + /** + * Return Allowed Countries reader + * + * @deprecated + * @return \Magento\Directory\Model\AllowedCountries + */ + private function getAllowedCountriesReader() + { + if (!$this->allowedCountriesReader) { + $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class); + } + + return $this->allowedCountriesReader; + } + /** * Load allowed countries for current store * @@ -126,16 +149,13 @@ protected function _construct() */ public function loadByStore($store = null) { - $allowCountries = explode(',', - (string)$this->_scopeConfig->getValue( - 'general/country/allow', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $store - ) - ); - if (!empty($allowCountries)) { - $this->addFieldToFilter("country_id", ['in' => $allowCountries]); + $allowedCountries = $this->getAllowedCountriesReader() + ->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store); + + if (!empty($allowedCountries)) { + $this->addFieldToFilter("country_id", ['in' => $allowedCountries]); } + return $this; } diff --git a/app/code/Magento/Directory/Model/ResourceModel/Country/Format.php b/app/code/Magento/Directory/Model/ResourceModel/Country/Format.php index 9ad4c485d26ea..c685bf80e21bb 100644 --- a/app/code/Magento/Directory/Model/ResourceModel/Country/Format.php +++ b/app/code/Magento/Directory/Model/ResourceModel/Country/Format.php @@ -1,6 +1,6 @@ allowedCountriesReader) { + $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class); + } + + return $this->allowedCountriesReader; + } + + /** + * Set allowed countries filter based on the given store. + * This is a convenience method for collection filtering based on store configuration settings. + * + * @param null|int|string|\Magento\Store\Model\Store $store + * @return \Magento\Directory\Model\ResourceModel\Region\Collection + */ + public function addAllowedCountriesFilter($store = null) + { + $allowedCountries = $this->getAllowedCountriesReader() + ->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store); + + if (!empty($allowedCountries)) { + $this->addFieldToFilter('main_table.country_id', ['in' => $allowedCountries]); + } + + return $this; + } + /** * Filter by country_id * diff --git a/app/code/Magento/Directory/Setup/InstallData.php b/app/code/Magento/Directory/Setup/InstallData.php index bacf3e000472a..ba259af6f8500 100644 --- a/app/code/Magento/Directory/Setup/InstallData.php +++ b/app/code/Magento/Directory/Setup/InstallData.php @@ -1,6 +1,6 @@ scopeConfigMock = $this->getMock(ScopeConfigInterface::class); + $this->storeManagerMock = $this->getMock(StoreManagerInterface::class); + + $this->allowedCountriesReader = new AllowedCountries( + $this->scopeConfigMock, + $this->storeManagerMock + ); + } + + public function testGetAllowedCountriesWithEmptyFilter() + { + $website1 = $this->getMock(WebsiteInterface::class); + $website1->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->storeManagerMock->expects($this->once()) + ->method('getWebsite') + ->willReturn($website1); + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with(AllowedCountries::ALLOWED_COUNTRIES_PATH, 'website', 1) + ->willReturn('AM'); + + $this->assertEquals(['AM' => 'AM'], $this->allowedCountriesReader->getAllowedCountries()); + } + + public function testGetAllowedCountries() + { + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with(AllowedCountries::ALLOWED_COUNTRIES_PATH, 'website', 1) + ->willReturn('AM'); + + $this->assertEquals( + ['AM' => 'AM'], + $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, 1) + ); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/Config/Source/AllRegionTest.php b/app/code/Magento/Directory/Test/Unit/Model/Config/Source/AllRegionTest.php index 354a59a9d0b48..804b745a40377 100644 --- a/app/code/Magento/Directory/Test/Unit/Model/Config/Source/AllRegionTest.php +++ b/app/code/Magento/Directory/Test/Unit/Model/Config/Source/AllRegionTest.php @@ -1,6 +1,6 @@ getMock(EntityFactory::class, [], [], '', false); $loggerMock = $this->getMock(LoggerInterface::class); $fetchStrategyMock = $this->getMock(FetchStrategyInterface::class); $eventManagerMock = $this->getMock(ManagerInterface::class); $localeResolverMock = $this->getMock(ResolverInterface::class); $connectionMock = $this->getMock(Mysql::class, [], [], '', false); - $resourceMock = $this->getMockForAbstractClass(AbstractDb::class, + $resourceMock = $this->getMockForAbstractClass( + AbstractDb::class, [], '', false, @@ -39,6 +54,7 @@ protected function setUp() true, ['getConnection', 'getMainTable', 'getTable', '__wakeup'] ); + $this->allowedCountries = $this->getMock(AllowedCountries::class, [], [], '', false); $selectMock = $this->getMock(Select::class, [], [], '', false); $connectionMock->expects($this->any())->method('select')->will($this->returnValue($selectMock)); @@ -54,6 +70,12 @@ protected function setUp() $connectionMock, $resourceMock ); + + $objectManager->setBackwardCompatibleProperty( + $this->collection, + 'allowedCountriesReader', + $this->allowedCountries + ); } public function testToOptionArray() @@ -98,4 +120,14 @@ public function testToOptionArray() $this->assertEquals($expectedResult, $this->collection->toOptionArray()); } + + public function testAddAllowedCountriesFilter() + { + $allowedCountries = [1, 2, 3]; + $this->allowedCountries->expects($this->once())->method('getAllowedCountries')->with( + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + null + )->willReturn($allowedCountries); + $this->assertEquals($this->collection->addAllowedCountriesFilter(), $this->collection); + } } diff --git a/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php index b68b91453964c..0abd98ce3faad 100644 --- a/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php +++ b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Directory/composer.json b/app/code/Magento/Directory/composer.json index 2f70ad4453b98..fad19febc0d52 100644 --- a/app/code/Magento/Directory/composer.json +++ b/app/code/Magento/Directory/composer.json @@ -2,7 +2,7 @@ "name": "magento/module-directory", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/module-config": "100.1.*", "magento/module-store": "100.1.*", "magento/module-backend": "100.1.*", @@ -10,7 +10,7 @@ "lib-libxml": "*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Directory/etc/adminhtml/di.xml b/app/code/Magento/Directory/etc/adminhtml/di.xml index 04c02acb98b12..8f85798987b5f 100644 --- a/app/code/Magento/Directory/etc/adminhtml/di.xml +++ b/app/code/Magento/Directory/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/adminhtml/routes.xml b/app/code/Magento/Directory/etc/adminhtml/routes.xml index f992e11ffb35a..301b06c4c75d2 100644 --- a/app/code/Magento/Directory/etc/adminhtml/routes.xml +++ b/app/code/Magento/Directory/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/adminhtml/system.xml b/app/code/Magento/Directory/etc/adminhtml/system.xml index dc56a23d20280..6232ddfdd287d 100644 --- a/app/code/Magento/Directory/etc/adminhtml/system.xml +++ b/app/code/Magento/Directory/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/config.xml b/app/code/Magento/Directory/etc/config.xml index 5c4de023286c8..b434865e00cfb 100644 --- a/app/code/Magento/Directory/etc/config.xml +++ b/app/code/Magento/Directory/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/crontab.xml b/app/code/Magento/Directory/etc/crontab.xml index 5e7a1da6e6c5a..825fb3e37f1eb 100644 --- a/app/code/Magento/Directory/etc/crontab.xml +++ b/app/code/Magento/Directory/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/di.xml b/app/code/Magento/Directory/etc/di.xml index f868197e60593..82e08bc8ec037 100644 --- a/app/code/Magento/Directory/etc/di.xml +++ b/app/code/Magento/Directory/etc/di.xml @@ -1,7 +1,7 @@ @@ -47,4 +47,12 @@ + + + + + 1 + + + diff --git a/app/code/Magento/Directory/etc/email_templates.xml b/app/code/Magento/Directory/etc/email_templates.xml index 8d5d3ebf9bdc7..65567fd7c3a6c 100644 --- a/app/code/Magento/Directory/etc/email_templates.xml +++ b/app/code/Magento/Directory/etc/email_templates.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/frontend/routes.xml b/app/code/Magento/Directory/etc/frontend/routes.xml index 79c92226d6446..303a7ab360a1d 100644 --- a/app/code/Magento/Directory/etc/frontend/routes.xml +++ b/app/code/Magento/Directory/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Directory/etc/frontend/sections.xml b/app/code/Magento/Directory/etc/frontend/sections.xml index fa48977872631..6f61593787460 100644 --- a/app/code/Magento/Directory/etc/frontend/sections.xml +++ b/app/code/Magento/Directory/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/module.xml b/app/code/Magento/Directory/etc/module.xml index 394060b473ff2..9d464d2788464 100644 --- a/app/code/Magento/Directory/etc/module.xml +++ b/app/code/Magento/Directory/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/webapi.xml b/app/code/Magento/Directory/etc/webapi.xml index 4794a2fe80944..1edd1191134c1 100644 --- a/app/code/Magento/Directory/etc/webapi.xml +++ b/app/code/Magento/Directory/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/zip_codes.xml b/app/code/Magento/Directory/etc/zip_codes.xml index e48a3c196aa45..1976c2cb46b25 100644 --- a/app/code/Magento/Directory/etc/zip_codes.xml +++ b/app/code/Magento/Directory/etc/zip_codes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/etc/zip_codes.xsd b/app/code/Magento/Directory/etc/zip_codes.xsd index ac6262480d343..399f997acc4d0 100644 --- a/app/code/Magento/Directory/etc/zip_codes.xsd +++ b/app/code/Magento/Directory/etc/zip_codes.xsd @@ -1,7 +1,7 @@ @@ -37,4 +37,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Directory/registration.php b/app/code/Magento/Directory/registration.php index 610af25ffffc2..58b24c70bdbf1 100644 --- a/app/code/Magento/Directory/registration.php +++ b/app/code/Magento/Directory/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml b/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml index f7d99f4a007f5..ce5b89f5f2b0b 100644 --- a/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml +++ b/app/code/Magento/Directory/view/adminhtml/templates/js/optional_zip_countries.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_index.xml b/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_index.xml index 7509438df2553..e01b48cc71b11 100644 --- a/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_index.xml +++ b/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_result.xml b/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_result.xml index 7509438df2553..e01b48cc71b11 100644 --- a/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_result.xml +++ b/app/code/Magento/Directory/view/frontend/layout/catalogsearch_advanced_result.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/view/frontend/layout/catalogsearch_result_index.xml b/app/code/Magento/Directory/view/frontend/layout/catalogsearch_result_index.xml index 7509438df2553..e01b48cc71b11 100644 --- a/app/code/Magento/Directory/view/frontend/layout/catalogsearch_result_index.xml +++ b/app/code/Magento/Directory/view/frontend/layout/catalogsearch_result_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/view/frontend/layout/default.xml b/app/code/Magento/Directory/view/frontend/layout/default.xml index e2cea7afc99cc..979fcd6e3d139 100644 --- a/app/code/Magento/Directory/view/frontend/layout/default.xml +++ b/app/code/Magento/Directory/view/frontend/layout/default.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Directory/view/frontend/templates/currency.phtml b/app/code/Magento/Directory/view/frontend/templates/currency.phtml index 9f575624008b0..125b635cde275 100644 --- a/app/code/Magento/Directory/view/frontend/templates/currency.phtml +++ b/app/code/Magento/Directory/view/frontend/templates/currency.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Downloadable/etc/adminhtml/di.xml b/app/code/Magento/Downloadable/etc/adminhtml/di.xml index a4f24ced94fcf..d6af2661df0f3 100644 --- a/app/code/Magento/Downloadable/etc/adminhtml/di.xml +++ b/app/code/Magento/Downloadable/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/adminhtml/menu.xml b/app/code/Magento/Downloadable/etc/adminhtml/menu.xml index 0fa664accfb66..55359b3045521 100644 --- a/app/code/Magento/Downloadable/etc/adminhtml/menu.xml +++ b/app/code/Magento/Downloadable/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/adminhtml/routes.xml b/app/code/Magento/Downloadable/etc/adminhtml/routes.xml index c2d077bdd680c..a3fca45339548 100644 --- a/app/code/Magento/Downloadable/etc/adminhtml/routes.xml +++ b/app/code/Magento/Downloadable/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/adminhtml/system.xml b/app/code/Magento/Downloadable/etc/adminhtml/system.xml index 2fdf6be5b88c3..a8f8315360339 100644 --- a/app/code/Magento/Downloadable/etc/adminhtml/system.xml +++ b/app/code/Magento/Downloadable/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/catalog_attributes.xml b/app/code/Magento/Downloadable/etc/catalog_attributes.xml index 7f3ae728853bd..081f9e8764b7f 100644 --- a/app/code/Magento/Downloadable/etc/catalog_attributes.xml +++ b/app/code/Magento/Downloadable/etc/catalog_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/config.xml b/app/code/Magento/Downloadable/etc/config.xml index d434ac16d068b..9582cea6da007 100644 --- a/app/code/Magento/Downloadable/etc/config.xml +++ b/app/code/Magento/Downloadable/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/di.xml b/app/code/Magento/Downloadable/etc/di.xml index 815868824ed25..84b6de602acaa 100644 --- a/app/code/Magento/Downloadable/etc/di.xml +++ b/app/code/Magento/Downloadable/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/events.xml b/app/code/Magento/Downloadable/etc/events.xml index eeafbf26ba4ec..da7cc5b5c9150 100644 --- a/app/code/Magento/Downloadable/etc/events.xml +++ b/app/code/Magento/Downloadable/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/extension_attributes.xml b/app/code/Magento/Downloadable/etc/extension_attributes.xml index 63789663921a2..c1d5f9e37c47e 100644 --- a/app/code/Magento/Downloadable/etc/extension_attributes.xml +++ b/app/code/Magento/Downloadable/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/fieldset.xml b/app/code/Magento/Downloadable/etc/fieldset.xml index 680857d7e5dcc..dfc475f4b27c2 100644 --- a/app/code/Magento/Downloadable/etc/fieldset.xml +++ b/app/code/Magento/Downloadable/etc/fieldset.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/frontend/di.xml b/app/code/Magento/Downloadable/etc/frontend/di.xml index a4b6dcd23e8f8..7920c2a5cf48b 100644 --- a/app/code/Magento/Downloadable/etc/frontend/di.xml +++ b/app/code/Magento/Downloadable/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/frontend/events.xml b/app/code/Magento/Downloadable/etc/frontend/events.xml index 0ea805bbfc921..3c024793a3744 100644 --- a/app/code/Magento/Downloadable/etc/frontend/events.xml +++ b/app/code/Magento/Downloadable/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/frontend/page_types.xml b/app/code/Magento/Downloadable/etc/frontend/page_types.xml index f8514e050a702..aabe2d70a3e41 100644 --- a/app/code/Magento/Downloadable/etc/frontend/page_types.xml +++ b/app/code/Magento/Downloadable/etc/frontend/page_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/frontend/routes.xml b/app/code/Magento/Downloadable/etc/frontend/routes.xml index 2e4df8f654331..0f5d7a974982d 100644 --- a/app/code/Magento/Downloadable/etc/frontend/routes.xml +++ b/app/code/Magento/Downloadable/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Downloadable/etc/module.xml b/app/code/Magento/Downloadable/etc/module.xml index a2fa1d9d569dd..580822fe957a1 100644 --- a/app/code/Magento/Downloadable/etc/module.xml +++ b/app/code/Magento/Downloadable/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/pdf.xml b/app/code/Magento/Downloadable/etc/pdf.xml index 2e71823cc690f..efc0e038a892e 100644 --- a/app/code/Magento/Downloadable/etc/pdf.xml +++ b/app/code/Magento/Downloadable/etc/pdf.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/product_types.xml b/app/code/Magento/Downloadable/etc/product_types.xml index 2f262cba218ba..08e02028965c0 100644 --- a/app/code/Magento/Downloadable/etc/product_types.xml +++ b/app/code/Magento/Downloadable/etc/product_types.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/sales.xml b/app/code/Magento/Downloadable/etc/sales.xml index adaddcdf672e2..2a10842dd3319 100644 --- a/app/code/Magento/Downloadable/etc/sales.xml +++ b/app/code/Magento/Downloadable/etc/sales.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/webapi.xml b/app/code/Magento/Downloadable/etc/webapi.xml index 06902aa646656..773b31ab2be66 100644 --- a/app/code/Magento/Downloadable/etc/webapi.xml +++ b/app/code/Magento/Downloadable/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/webapi_rest/di.xml b/app/code/Magento/Downloadable/etc/webapi_rest/di.xml index a4aa62194a39c..6e1c41b1c9606 100644 --- a/app/code/Magento/Downloadable/etc/webapi_rest/di.xml +++ b/app/code/Magento/Downloadable/etc/webapi_rest/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/etc/webapi_soap/di.xml b/app/code/Magento/Downloadable/etc/webapi_soap/di.xml index a4aa62194a39c..6e1c41b1c9606 100644 --- a/app/code/Magento/Downloadable/etc/webapi_soap/di.xml +++ b/app/code/Magento/Downloadable/etc/webapi_soap/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/registration.php b/app/code/Magento/Downloadable/registration.php index 0164a72a02b91..516a177e10c1c 100644 --- a/app/code/Magento/Downloadable/registration.php +++ b/app/code/Magento/Downloadable/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_simple.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_simple.xml index 0eeed489a5ed0..5866d21ff46d7 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_simple.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_simple.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_view_type_downloadable.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_view_type_downloadable.xml index 1661a7be27d60..823b83c7cdf33 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_view_type_downloadable.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_view_type_downloadable.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_virtual.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_virtual.xml index 0eeed489a5ed0..5866d21ff46d7 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_virtual.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/catalog_product_virtual.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/customer_index_wishlist.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/customer_index_wishlist.xml index be88b8b88771e..1355e7a0c8562 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/customer_index_wishlist.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/customer_index_wishlist.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/downloadable_items.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/downloadable_items.xml index 0d7bb35904d26..5a8056106444f 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/downloadable_items.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/downloadable_items.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_new.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_new.xml index 7206a5e8aa877..50c7e06227afb 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_new.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml index 7206a5e8aa877..50c7e06227afb 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_view.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_view.xml index 9c221ebbfe46d..d06b80071892e 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_view.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_creditmemo_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_new.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_new.xml index 0aa400ff3a5a4..9b3c2af9d0ff4 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_new.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_updateqty.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_updateqty.xml index 0aa400ff3a5a4..9b3c2af9d0ff4 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_updateqty.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_updateqty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_view.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_view.xml index 8eb1288dd4c6b..dfbbe17392e2e 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_view.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_invoice_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_view.xml b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_view.xml index 61d85ae24f5dd..d2e7658639935 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_view.xml +++ b/app/code/Magento/Downloadable/view/adminhtml/layout/sales_order_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml index ace16699931a3..ff66ccd5dc73b 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/product/composite/fieldset/downloadable.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_configure_type_downloadable.xml b/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_configure_type_downloadable.xml index f1e267b259c28..6d0c8b366f853 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_configure_type_downloadable.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_configure_type_downloadable.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_item_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_item_renderers.xml index 6caf33617e6f3..4840c49e24c5a 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_item_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/checkout_cart_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_review_item_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_review_item_renderers.xml index 586b24e070148..104ba3cba6ab0 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_review_item_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_review_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_success.xml b/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_success.xml index f3fc88ae57a9f..8307b3f4630cb 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_success.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/checkout_onepage_success.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/customer_account.xml b/app/code/Magento/Downloadable/view/frontend/layout/customer_account.xml index 8d4f13f2bfb16..69cca93e72b54 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/customer_account.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/customer_account.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/downloadable_customer_products.xml b/app/code/Magento/Downloadable/view/frontend/layout/downloadable_customer_products.xml index 991015cba9af3..b548547224aa3 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/downloadable_customer_products.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/downloadable_customer_products.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/multishipping_checkout_success.xml b/app/code/Magento/Downloadable/view/frontend/layout/multishipping_checkout_success.xml index 29902fd07014a..62080117ae55e 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/multishipping_checkout_success.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/multishipping_checkout_success.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 6b58d2be20e2e..b7519ba763a27 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_invoice_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_invoice_renderers.xml index d8e04774ba9fb..8fd23a49cd90f 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_invoice_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_renderers.xml index c8a59438f7a33..e3d68ac505ff0 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_email_order_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_creditmemo_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_creditmemo_renderers.xml index 17c2dc1803799..b08ad83799117 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_creditmemo_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_invoice_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_invoice_renderers.xml index a6456830b403d..243dd2124f406 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_invoice_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_item_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_item_renderers.xml index 85aa800ca9e0e..ca8af720a7c16 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_item_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_creditmemo_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_creditmemo_renderers.xml index 393428217da47..82ce1a00df1ed 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_creditmemo_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_invoice_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_invoice_renderers.xml index 903266531c91a..565567d0835da 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_invoice_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_renderers.xml b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_renderers.xml index 1bc8a1feb1db2..7053a0643a36e 100644 --- a/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_renderers.xml +++ b/app/code/Magento/Downloadable/view/frontend/layout/sales_order_print_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Downloadable/view/frontend/requirejs-config.js b/app/code/Magento/Downloadable/view/frontend/requirejs-config.js index b96ac9961b1e7..1a27eb7d5ff79 100644 --- a/app/code/Magento/Downloadable/view/frontend/requirejs-config.js +++ b/app/code/Magento/Downloadable/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,4 +9,4 @@ var config = { downloadable: 'Magento_Downloadable/downloadable' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/links.phtml b/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/links.phtml index 908a956fec1db..e8f8d2d93f2f8 100644 --- a/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/links.phtml +++ b/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/links.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/DownloadableImportExport/etc/module.xml b/app/code/Magento/DownloadableImportExport/etc/module.xml index e3be073f07462..be3e7a67690eb 100644 --- a/app/code/Magento/DownloadableImportExport/etc/module.xml +++ b/app/code/Magento/DownloadableImportExport/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/DownloadableImportExport/registration.php b/app/code/Magento/DownloadableImportExport/registration.php index bd61216c039d4..e94d3ff9b415a 100644 --- a/app/code/Magento/DownloadableImportExport/registration.php +++ b/app/code/Magento/DownloadableImportExport/registration.php @@ -1,6 +1,6 @@ numberFormatterFactory === null) { + $this->numberFormatterFactory = \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\Intl\NumberFormatterFactory::class + ); + } + return $this->numberFormatterFactory; + } + /** * Prepare data for save * @@ -256,7 +278,8 @@ public function beforeSave() $hasDefaultValue = (string)$defaultValue != ''; if ($this->getBackendType() == 'decimal' && $hasDefaultValue) { - $numberFormatter = new \NumberFormatter($this->_localeResolver->getLocale(), \NumberFormatter::DECIMAL); + $numberFormatter = $this->getNumberFormatterFactory() + ->create($this->_localeResolver->getLocale(), \NumberFormatter::DECIMAL); $defaultValue = $numberFormatter->parse($defaultValue); if ($defaultValue === false) { throw new LocalizedException(__('Invalid default decimal value')); @@ -498,6 +521,7 @@ public function getIdentities() */ public function __sleep() { + $this->unsetData('attribute_set_info'); return array_diff( parent::__sleep(), ['_localeDate', '_localeResolver', 'reservedAttributeList', 'dateTimeFormatter'] diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 7e40bbd482f83..96cd1f8b19525 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -1,13 +1,13 @@ getBackend()->getType(); return (is_array($value) && count($value) == 0) || $value === null - || ($value === false && $attributeType != 'int') - || ($value === '' && in_array($attributeType, $emptyStringTypes)); + || ($value === false && $this->getBackend()->getType() != 'int') + || ($value === '' && in_array($this->getBackend()->getType(), $emptyStringTypes)); } /** diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AttributeInterface.php b/app/code/Magento/Eav/Model/Entity/Attribute/AttributeInterface.php index f620bd0c90356..44a747775153f 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AttributeInterface.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AttributeInterface.php @@ -1,6 +1,6 @@ _attrBooleanFactory = $attrBooleanFactory; + $this->cache = $cache ?: ObjectManager::getInstance()->get(CacheInterface::class); + $this->cacheTags = !empty($cacheTags) ? $cacheTags : self::$defaultCacheTags; + $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class); } /** @@ -216,7 +257,21 @@ public function getConfigField($fieldName) */ public function getSelectOptions() { - return $this->getAttribute()->getSource()->getAllOptions(); + $cacheKey = 'attribute-navigation-option-' . + $this->getAttribute()->getAttributeCode() . '-' . + $this->storeManager->getStore()->getId(); + $optionString = $this->cache->load($cacheKey); + if (false === $optionString) { + $options = $this->getAttribute()->getSource()->getAllOptions(); + $this->cache->save( + json_encode($options), + $cacheKey, + $this->cacheTags + ); + } else { + $options = json_decode($optionString, true); + } + return $options; } /** diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Frontend/Datetime.php b/app/code/Magento/Eav/Model/Entity/Attribute/Frontend/Datetime.php index 2fe234f05fd90..4180ef91163e9 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Frontend/Datetime.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Frontend/Datetime.php @@ -1,6 +1,6 @@ getLoadAllAttributesCacheSuffix($object); + $typeCode = $resource->getEntityType()->getEntityTypeCode(); - $attributes = $this->cache->getAttributes($typeCode); + $attributes = $this->cache->getAttributes($typeCode, $suffix); if ($attributes) { foreach ($attributes as $attribute) { $resource->addAttribute($attribute); } return $resource; } + $attributes = $this->checkAndInitAttributes($resource, $object); + $this->cache->saveAttributes($typeCode, $attributes, $suffix); + return $resource; + } + + /** + * @param AbstractEntity $resource + * @param DataObject|null $object + * @return array + */ + private function checkAndInitAttributes(AbstractEntity $resource, DataObject $object = null) + { $attributeCodes = $this->config->getEntityAttributeCodes($resource->getEntityType(), $object); $attributes = []; + /** * Check and init default attributes */ @@ -95,8 +110,23 @@ public function loadAllAttributes(AbstractEntity $resource, DataObject $object = $attribute = $resource->getAttribute($code); $attributes[] = $attribute; } - $this->cache->saveAttributes($typeCode, $attributes); - return $resource; + return $attributes; + } + + /** + * @param DataObject|null $object + * @return string + */ + private function getLoadAllAttributesCacheSuffix(DataObject $object = null) + { + $attributeSetId = 0; + $storeId = 0; + if (null !== $object) { + $attributeSetId = $object->getAttributeSetId() ?: $attributeSetId; + $storeId = $object->getStoreId() ?: $storeId; + } + $suffix = $storeId . '-' . $attributeSetId; + return $suffix; } /** diff --git a/app/code/Magento/Eav/Model/Entity/AttributeLoaderInterface.php b/app/code/Magento/Eav/Model/Entity/AttributeLoaderInterface.php index 640175c341ec2..6e796bae48883 100644 --- a/app/code/Magento/Eav/Model/Entity/AttributeLoaderInterface.php +++ b/app/code/Magento/Eav/Model/Entity/AttributeLoaderInterface.php @@ -1,6 +1,6 @@ attributeRepository = $attributeRepository; + $this->metadataPool = $metadataPool; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->attributeCache = $attributeCache; + } + + /** + * Get attributes list from attribute set + * + * @param string $entityType + * @param int $attributeSetId + * @return \Magento\Eav\Api\Data\AttributeInterface[]|\object[] + */ + public function getAttributes($entityType, $attributeSetId = null) + { + $suffix = self::ATTRIBUTE_SET_ID . '-' . ($attributeSetId ?: 'all'); + if ($attributes = $this->attributeCache->getAttributes($entityType, $suffix)) { + return $attributes; + } + + $metadata = $this->metadataPool->getMetadata($entityType); + + if ($attributeSetId === null) { + $criteria = $this->searchCriteriaBuilder->addFilter(self::ATTRIBUTE_SET_ID, null, 'neq')->create(); + } else { + $criteria = $this->searchCriteriaBuilder->addFilter(self::ATTRIBUTE_SET_ID, $attributeSetId)->create(); + } + + $searchResult = $this->attributeRepository->getList( + $metadata->getEavEntityType(), + $criteria + ); + $attributes = $searchResult->getItems(); + + $this->attributeCache->saveAttributes( + $entityType, + $attributes, + $suffix + ); + return $attributes; + } +} diff --git a/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php b/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php index 74373cb593c40..e983b0de20018 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php +++ b/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php @@ -1,6 +1,6 @@ metadataPool->getMetadata($entityType); + $linkField = $metadata->getLinkField(); foreach ($this->delete[$entityType] as $link => $data) { $attributeCodes = array_keys($data); foreach ($attributeCodes as $attributeCode) { /** @var AbstractAttribute $attribute */ $attribute = $this->attributeRepository->get($metadata->getEavEntityType(), $attributeCode); $conditions = [ - $metadata->getLinkField() . ' = ?' => $link, + $linkField . ' = ?' => $link, 'attribute_id = ?' => $attribute->getAttributeId() ]; foreach ($context as $scope) { @@ -147,6 +148,7 @@ public function processInserts($entityType, $context) return; } $metadata = $this->metadataPool->getMetadata($entityType); + $linkField = $metadata->getLinkField(); foreach ($this->insert[$entityType] as $link => $data) { foreach ($data as $attributeCode => $attributeValue) { /** @var AbstractAttribute $attribute */ @@ -155,7 +157,7 @@ public function processInserts($entityType, $context) $attributeCode ); $data = [ - $metadata->getLinkField() => $link, + $linkField => $link, 'attribute_id' => $attribute->getAttributeId(), 'value' => $this->prepareValue($entityType, $attributeValue, $attribute) ]; @@ -180,6 +182,7 @@ public function processUpdates($entityType, $context) return; } $metadata = $this->metadataPool->getMetadata($entityType); + $linkField = $metadata->getLinkField(); foreach ($this->update[$entityType] as $link => $data) { foreach ($data as $attributeCode => $attributeValue) { /** @var AbstractAttribute $attribute */ @@ -188,7 +191,7 @@ public function processUpdates($entityType, $context) $attributeCode ); $conditions = [ - $metadata->getLinkField() . ' = ?' => $link, + $linkField . ' = ?' => $link, 'attribute_id = ?' => $attribute->getAttributeId(), ]; foreach ($context as $scope) { diff --git a/app/code/Magento/Eav/Model/ResourceModel/Config.php b/app/code/Magento/Eav/Model/ResourceModel/Config.php index 661861e69244d..00fe4472d7d7a 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Config.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Config.php @@ -1,6 +1,6 @@ attributeRepository = $attributeRepository; $this->metadataPool = $metadataPool; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->attributePersistor = $attributePersistor; $this->scopeResolver = $scopeResolver; + $this->attributeLoader = $attributeLoader ?: ObjectManager::getInstance()->get(AttributeLoader::class); } /** * @param string $entityType + * @param int $attributeSetId * @return \Magento\Eav\Api\Data\AttributeInterface[] - * @throws \Exception */ - protected function getAttributes($entityType) + protected function getAttributes($entityType, $attributeSetId = null) { - $metadata = $this->metadataPool->getMetadata($entityType); - $searchResult = $this->attributeRepository->getList( - $metadata->getEavEntityType(), - $this->searchCriteriaBuilder->addFilter('attribute_set_id', null, 'neq')->create() - ); - return $searchResult->getItems(); + return $this->attributeLoader->getAttributes($entityType, $attributeSetId); } /** @@ -92,23 +96,28 @@ public function execute($entityType, $entityData, $arguments = []) $metadata = $this->metadataPool->getMetadata($entityType); if ($metadata->getEavEntityType()) { $processed = []; + $entityLinkField = $metadata->getLinkField(); + $attributeSetId = isset($entityData[AttributeLoader::ATTRIBUTE_SET_ID]) + ? $entityData[AttributeLoader::ATTRIBUTE_SET_ID] + : null; // @todo verify is it normal to not have attributer_set_id /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */ - foreach ($this->getAttributes($entityType) as $attribute) { + foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) { if ($attribute->isStatic()) { continue; } - if (isset($entityData[$attribute->getAttributeCode()]) - && !is_array($entityData[$attribute->getAttributeCode()]) - && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()]) + + $attributeCode = $attribute->getAttributeCode(); + if (isset($entityData[$attributeCode]) + && !is_array($entityData[$attributeCode]) + && !$attribute->isValueEmpty($entityData[$attributeCode]) ) { - $entityLinkField = $metadata->getLinkField(); $this->attributePersistor->registerInsert( $entityType, $entityData[$entityLinkField], - $attribute->getAttributeCode(), - $entityData[$attribute->getAttributeCode()] + $attributeCode, + $entityData[$attributeCode] ); - $processed[$attribute->getAttributeCode()] = $entityData[$attribute->getAttributeCode()]; + $processed[$attributeCode] = $entityData[$attributeCode]; } } $context = $this->scopeResolver->getEntityContext($entityType, $entityData); diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php index a62637c9a93b4..fe39372926202 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php @@ -1,6 +1,6 @@ attributeCache = $attributeCache; } + /** + * Get Logger + * + * @return LoggerInterface + * @deprecated + */ + private function getLogger() + { + if ($this->logger === null) { + $this->logger = \Magento\Framework\App\ObjectManager::getInstance()->create(LoggerInterface::class); + } + return $this->logger; + } + /** * @param string $entityType * @return \Magento\Eav\Api\Data\AttributeInterface[] @@ -82,7 +102,6 @@ public function __construct( */ protected function getAttributes($entityType) { - $attributes = $this->attributeCache->getAttributes($entityType); if ($attributes) { return $attributes; @@ -163,7 +182,14 @@ public function execute($entityType, $entityData, $arguments = []) \Magento\Framework\DB\Select::SQL_UNION_ALL ); foreach ($connection->fetchAll($unionSelect) as $attributeValue) { - $entityData[$attributesMap[$attributeValue['attribute_id']]] = $attributeValue['value']; + if (isset($attributesMap[$attributeValue['attribute_id']])) { + $entityData[$attributesMap[$attributeValue['attribute_id']]] = $attributeValue['value']; + } else { + $this->getLogger()->warning( + "Attempt to load value of nonexistent EAV attribute '{$attributeValue['attribute_id']}' + for entity type '$entityType'." + ); + } } } return $entityData; diff --git a/app/code/Magento/Eav/Model/ResourceModel/ReadSnapshot.php b/app/code/Magento/Eav/Model/ResourceModel/ReadSnapshot.php index 4ef01cb59dd96..3060ce7aaefaf 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/ReadSnapshot.php +++ b/app/code/Magento/Eav/Model/ResourceModel/ReadSnapshot.php @@ -1,6 +1,6 @@ attributeRepository = $attributeRepository; $this->metadataPool = $metadataPool; @@ -77,22 +84,17 @@ public function __construct( $this->attributePersistor = $attributePersistor; $this->readSnapshot = $readSnapshot; $this->scopeResolver = $scopeResolver; + $this->attributeLoader = $attributeLoader ?: ObjectManager::getInstance()->get(AttributeLoader::class); } /** * @param string $entityType + * @param int $attributeSetId * @return \Magento\Eav\Api\Data\AttributeInterface[] - * @throws \Exception */ - protected function getAttributes($entityType) + protected function getAttributes($entityType, $attributeSetId = null) { - $metadata = $this->metadataPool->getMetadata($entityType); - - $searchResult = $this->attributeRepository->getList( - $metadata->getEavEntityType(), - $this->searchCriteriaBuilder->addFilter('attribute_set_id', null, 'neq')->create() - ); - return $searchResult->getItems(); + return $this->attributeLoader->getAttributes($entityType, $attributeSetId); } /** @@ -118,8 +120,11 @@ public function execute($entityType, $entityData, $arguments = []) $entityDataForSnapshot[$scope->getIdentifier()] = $entityData[$scope->getIdentifier()]; } } + $attributeSetId = isset($entityData[AttributeLoader::ATTRIBUTE_SET_ID]) + ? $entityData[AttributeLoader::ATTRIBUTE_SET_ID] + : null; // @todo verify is it normal to not have attributer_set_id $snapshot = $this->readSnapshot->execute($entityType, $entityDataForSnapshot); - foreach ($this->getAttributes($entityType) as $attribute) { + foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) { if ($attribute->isStatic()) { continue; } diff --git a/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php b/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php index ed76965e02f23..1b572180ab9d7 100644 --- a/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php +++ b/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php @@ -1,6 +1,6 @@ $this->_getValue($params, 'additional_attribute_table'), 'entity_attribute_collection' => $this->_getValue($params, 'entity_attribute_collection'), ]; + if (isset($params['entity_type_id'])) { + $data['entity_type_id'] = $params['entity_type_id']; + } if ($this->getEntityType($code, 'entity_type_id')) { $this->updateEntityType($code, $data); @@ -199,7 +202,11 @@ public function addEntityType($code, array $params) $this->setup->getConnection()->insert($this->setup->getTable('eav_entity_type'), $data); } - $this->addAttributeSet($code, $this->_defaultAttributeSetName); + if (isset($params['entity_type_id'])) { + $this->addAttributeSet($code, $this->_defaultAttributeSetName, null, $params['entity_type_id']); + } else { + $this->addAttributeSet($code, $this->_defaultAttributeSetName); + } $this->addAttributeGroup($code, $this->_defaultGroupName, $this->_generalGroupName); return $this; @@ -310,9 +317,10 @@ public function getAttributeSetSortOrder($entityTypeId, $sortOrder = null) * @param int|string $entityTypeId * @param string $name * @param int $sortOrder + * @param int $setId * @return $this */ - public function addAttributeSet($entityTypeId, $name, $sortOrder = null) + public function addAttributeSet($entityTypeId, $name, $sortOrder = null, $setId = null) { $data = [ 'entity_type_id' => $this->getEntityTypeId($entityTypeId), @@ -320,6 +328,10 @@ public function addAttributeSet($entityTypeId, $name, $sortOrder = null) 'sort_order' => $this->getAttributeSetSortOrder($entityTypeId, $sortOrder), ]; + if ($setId !== null) { + $data['attribute_set_id'] = $setId; + } + $setId = $this->getAttributeSet($entityTypeId, $name, 'attribute_set_id'); if ($setId) { $this->updateAttributeSet($entityTypeId, $setId, $data); diff --git a/app/code/Magento/Eav/Setup/InstallData.php b/app/code/Magento/Eav/Setup/InstallData.php index fa6b329d3768c..75bafe1520ca3 100644 --- a/app/code/Magento/Eav/Setup/InstallData.php +++ b/app/code/Magento/Eav/Setup/InstallData.php @@ -1,6 +1,6 @@ expects($this->any())->method('getType')->willReturn($attributeType); - $model->expects($this->once())->method('getBackend')->willReturn($backendModelMock); + $model->expects($this->any())->method('getBackend')->willReturn($backendModelMock); $this->assertEquals($isEmpty, $model->isValueEmpty($value)); } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/AbstractTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/AbstractTest.php index 7c6db8ccff7a5..02d782bf871f1 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/AbstractTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/AbstractTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Config/_files/invalidEavAttributeXmlArray.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Config/_files/invalidEavAttributeXmlArray.php index 3e56fdaa079b2..7a78f5d3319b2 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Config/_files/invalidEavAttributeXmlArray.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Config/_files/invalidEavAttributeXmlArray.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Eav/etc/config.xml b/app/code/Magento/Eav/etc/config.xml index f7ef6bb445673..2271c370266ad 100644 --- a/app/code/Magento/Eav/etc/config.xml +++ b/app/code/Magento/Eav/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Eav/etc/di.xml b/app/code/Magento/Eav/etc/di.xml index ae230ca193a98..570b71fc5a8e8 100644 --- a/app/code/Magento/Eav/etc/di.xml +++ b/app/code/Magento/Eav/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Eav/etc/eav_attributes.xsd b/app/code/Magento/Eav/etc/eav_attributes.xsd index d6669c042f2da..578838d8da2e6 100644 --- a/app/code/Magento/Eav/etc/eav_attributes.xsd +++ b/app/code/Magento/Eav/etc/eav_attributes.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Eav/etc/extension_attributes.xml b/app/code/Magento/Eav/etc/extension_attributes.xml index 19e2e8a66fb38..d2cf83bd8aee3 100644 --- a/app/code/Magento/Eav/etc/extension_attributes.xml +++ b/app/code/Magento/Eav/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Eav/etc/module.xml b/app/code/Magento/Eav/etc/module.xml index c1c313d915019..2de67ac46b1dd 100644 --- a/app/code/Magento/Eav/etc/module.xml +++ b/app/code/Magento/Eav/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Eav/etc/validation.xml b/app/code/Magento/Eav/etc/validation.xml index b7f7016a4e9b4..4afe79aac155a 100644 --- a/app/code/Magento/Eav/etc/validation.xml +++ b/app/code/Magento/Eav/etc/validation.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Eav/etc/webapi.xml b/app/code/Magento/Eav/etc/webapi.xml index b14ab4514e084..2c84241ac9d07 100644 --- a/app/code/Magento/Eav/etc/webapi.xml +++ b/app/code/Magento/Eav/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Eav/registration.php b/app/code/Magento/Eav/registration.php index fba2c277fc218..ce31dcc9e679b 100644 --- a/app/code/Magento/Eav/registration.php +++ b/app/code/Magento/Eav/registration.php @@ -1,6 +1,6 @@ filesystem->getDirectoryRead(DirectoryList::MEDIA); if ($mediaDirectory->isFile($uploadDir . '/' . $fileName)) { return $this->storeManager->getStore()->getBaseUrl( diff --git a/app/code/Magento/Email/Model/BackendTemplate.php b/app/code/Magento/Email/Model/BackendTemplate.php index bbdec786c7b06..c27b6428cb909 100644 --- a/app/code/Magento/Email/Model/BackendTemplate.php +++ b/app/code/Magento/Email/Model/BackendTemplate.php @@ -1,6 +1,6 @@ assetRepository = $assetRepository; + } + + /** + * Process css placeholders + * + * @param string $css + * @return string + */ + public function process($css) + { + $matches = []; + if (preg_match_all(Variable::VAR_REGEX, $css, $matches, PREG_SET_ORDER)) { + $replacements = []; + foreach ($matches as $match) { + if (!isset($replacements[$match[0]])) { + $replacements[$match[0]] = $this->getPlaceholderValue($match[1]); + } + } + $css = str_replace(array_keys($replacements), $replacements, $css); + } + return $css; + } + + /** + * Retrieve placeholder value + * + * @param string $placeholder + * @return string + */ + private function getPlaceholderValue($placeholder) + { + /** @var \Magento\Framework\View\Asset\File\FallbackContext $context */ + $context = $this->assetRepository->getStaticViewFileContext(); + + switch ($placeholder) { + case 'base_url_path': + return $context->getBaseUrl(); + case 'locale': + return $context->getLocale(); + default: + return ''; + } + } +} diff --git a/app/code/Magento/Email/Model/Template/Filter.php b/app/code/Magento/Email/Model/Template/Filter.php index 3d2631145635a..14a0566f7c0e6 100644 --- a/app/code/Magento/Email/Model/Template/Filter.php +++ b/app/code/Magento/Email/Model/Template/Filter.php @@ -1,10 +1,13 @@ cssProcessor) { + $this->cssProcessor = ObjectManager::getInstance()->get(Css\Processor::class); + } + return $this->cssProcessor; + } + + /** + * @deprecated + * @param string $dirType + * @return ReadInterface + */ + private function getPubDirectory($dirType) + { + if (!$this->pubDirectory) { + $this->pubDirectory = ObjectManager::getInstance()->get(Filesystem::class)->getDirectoryRead($dirType); + } + return $this->pubDirectory; + } + /** * Get design parameters * @@ -788,7 +826,9 @@ public function cssDirective($construction) return '/* ' . __('"file" parameter must be specified') . ' */'; } - $css = $this->getCssFilesContent([$params['file']]); + $css = $this->getCssProcessor()->process( + $this->getCssFilesContent([$params['file']]) + ); if (strpos($css, ContentProcessorInterface::ERROR_MESSAGE_PREFIX) !== false) { // Return compilation error wrapped in CSS comment @@ -889,7 +929,12 @@ public function getCssFilesContent(array $files) try { foreach ($files as $file) { $asset = $this->_assetRepo->createAsset($file, $designParams); - $css .= $asset->getContent(); + $pubDirectory = $this->getPubDirectory($asset->getContext()->getBaseDirType()); + if ($pubDirectory->isExist($asset->getPath())) { + $css .= $pubDirectory->readFile($asset->getPath()); + } else { + $css .= $asset->getContent(); + } } } catch (ContentProcessorException $exception) { $css = $exception->getMessage(); @@ -914,6 +959,7 @@ public function applyInlineCss($html) $cssToInline = $this->getCssFilesContent( $this->getInlineCssFiles() ); + $cssToInline = $this->getCssProcessor()->process($cssToInline); // Only run Emogrify if HTML and CSS contain content if ($html && $cssToInline) { try { diff --git a/app/code/Magento/Email/Model/Template/SenderResolver.php b/app/code/Magento/Email/Model/Template/SenderResolver.php index 853c9274a6523..1ee8d3880decd 100644 --- a/app/code/Magento/Email/Model/Template/SenderResolver.php +++ b/app/code/Magento/Email/Model/Template/SenderResolver.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/Fixture/ModuleTwo/etc/email_templates_two.xml b/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/Fixture/ModuleTwo/etc/email_templates_two.xml index 6d98d47380e3d..8b698fb496f14 100644 --- a/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/Fixture/ModuleTwo/etc/email_templates_two.xml +++ b/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/Fixture/ModuleTwo/etc/email_templates_two.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/email_templates_merged.php b/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/email_templates_merged.php index b6cddd94f0026..9ca1a4395cec5 100644 --- a/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/email_templates_merged.php +++ b/app/code/Magento/Email/Test/Unit/Model/Template/Config/_files/email_templates_merged.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php b/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php index b4676b2c4d396..f2d5da5a29ac4 100644 --- a/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php @@ -1,6 +1,6 @@ assetRepository = $this->getMockBuilder(Repository::class) + ->disableOriginalConstructor() + ->getMock(); + $this->fallbackContext = $this->getMockBuilder(FallbackContext::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->processor = new Processor($this->assetRepository); + } + + public function testProcess() + { + $url = 'http://magento.local/pub/static/'; + $locale = 'en_US'; + $css = '@import url("{{base_url_path}}frontend/_view/{{locale}}/css/email.css");'; + $expectedCss = '@import url("' . $url . 'frontend/_view/' . $locale . '/css/email.css");'; + + $this->assetRepository->expects($this->exactly(2)) + ->method('getStaticViewFileContext') + ->willReturn($this->fallbackContext); + $this->fallbackContext->expects($this->once()) + ->method('getBaseUrl') + ->willReturn($url); + $this->fallbackContext->expects($this->once()) + ->method('getLocale') + ->willReturn($locale); + $this->assertEquals($expectedCss, $this->processor->process($css)); + } +} diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php b/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php index 3d1673a6e8463..be2e1604d92eb 100644 --- a/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/Template/FilterTest.php @@ -1,10 +1,17 @@ objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->string = $this->getMockBuilder('\Magento\Framework\Stdlib\StringUtils') + $this->string = $this->getMockBuilder(\Magento\Framework\Stdlib\StringUtils::class) ->disableOriginalConstructor() ->getMock(); - $this->logger = $this->getMockBuilder('\Psr\Log\LoggerInterface') + $this->logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->escaper = $this->getMockBuilder('\Magento\Framework\Escaper') + $this->escaper = $this->getMockBuilder(\Magento\Framework\Escaper::class) ->disableOriginalConstructor() - ->enableProxyingToOriginalMethods() ->getMock(); - $this->assetRepo = $this->getMockBuilder('\Magento\Framework\View\Asset\Repository') + $this->assetRepo = $this->getMockBuilder(\Magento\Framework\View\Asset\Repository::class) ->disableOriginalConstructor() ->getMock(); - $this->scopeConfig = $this->getMockBuilder('\Magento\Framework\App\Config\ScopeConfigInterface') + $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->coreVariableFactory = $this->getMockBuilder('\Magento\Variable\Model\VariableFactory') + $this->coreVariableFactory = $this->getMockBuilder(\Magento\Variable\Model\VariableFactory::class) ->disableOriginalConstructor() ->getMock(); - $this->storeManager = $this->getMockBuilder('\Magento\Store\Model\StoreManagerInterface') + $this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->layout = $this->getMockBuilder('\Magento\Framework\View\LayoutInterface') + $this->layout = $this->getMockBuilder(\Magento\Framework\View\LayoutInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->layoutFactory = $this->getMockBuilder('\Magento\Framework\View\LayoutFactory') + $this->layoutFactory = $this->getMockBuilder(\Magento\Framework\View\LayoutFactory::class) ->disableOriginalConstructor() ->getMock(); - $this->appState = $this->getMockBuilder('\Magento\Framework\App\State') + $this->appState = $this->getMockBuilder(\Magento\Framework\App\State::class) ->disableOriginalConstructor() ->getMock(); - $this->backendUrlBuilder = $this->getMockBuilder('\Magento\Backend\Model\UrlInterface') + $this->backendUrlBuilder = $this->getMockBuilder(\Magento\Backend\Model\UrlInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->emogrifier = $this->objectManager->getObject('\Pelago\Emogrifier'); + $this->emogrifier = $this->objectManager->getObject(\Pelago\Emogrifier::class); - $this->configVariables = $this->getMockBuilder('Magento\Email\Model\Source\Variables') + $this->configVariables = $this->getMockBuilder(\Magento\Email\Model\Source\Variables::class) ->disableOriginalConstructor() ->getMock(); } /** * @param array|null $mockedMethods Methods to mock - * @return \Magento\Email\Model\Template\Filter|\PHPUnit_Framework_MockObject_MockObject + * @return Filter|\PHPUnit_Framework_MockObject_MockObject */ protected function getModel($mockedMethods = null) { - return $this->getMockBuilder('\Magento\Email\Model\Template\Filter') + return $this->getMockBuilder(\Magento\Email\Model\Template\Filter::class) ->setConstructorArgs([ $this->string, $this->logger, @@ -252,13 +258,24 @@ public function transDirectiveDataProvider() public function testApplyInlineCss($html, $css, $expectedResults) { $filter = $this->getModel(['getCssFilesContent']); + $cssProcessor = $this->getMockBuilder(Processor::class) + ->setMethods(['process']) + ->disableOriginalConstructor() + ->getMock(); + $reflectionClass = new \ReflectionClass(Filter::class); + $reflectionProperty = $reflectionClass->getProperty('cssProcessor'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($filter, $cssProcessor); + $cssProcessor->expects($this->any()) + ->method('process') + ->willReturnArgument(0); $filter->expects($this->exactly(count($expectedResults))) ->method('getCssFilesContent') ->will($this->returnValue($css)); $designParams = [ - 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, + 'area' => Area::AREA_FRONTEND, 'theme' => 'themeId', 'locale' => 'localeId', ]; @@ -269,6 +286,60 @@ public function testApplyInlineCss($html, $css, $expectedResults) } } + public function testGetCssFilesContent() + { + $file = 'css/email.css'; + $path = Area::AREA_FRONTEND . '/themeId/localeId'; + $css = 'p{color:black}'; + $designParams = [ + 'area' => Area::AREA_FRONTEND, + 'theme' => 'themeId', + 'locale' => 'localeId', + ]; + $filter = $this->getModel(); + + $asset = $this->getMockBuilder(\Magento\Framework\View\Asset\File::class) + ->disableOriginalConstructor() + ->getMock(); + + $fallbackContext = $this->getMockBuilder(FallbackContext::class) + ->disableOriginalConstructor() + ->getMock(); + $fallbackContext->expects($this->once()) + ->method('getBaseDirType') + ->willReturn(DirectoryList::STATIC_VIEW); + $asset->expects($this->atLeastOnce()) + ->method('getContext') + ->willReturn($fallbackContext); + + $asset->expects($this->atLeastOnce()) + ->method('getPath') + ->willReturn($path . DIRECTORY_SEPARATOR . $file); + $this->assetRepo->expects($this->once()) + ->method('createAsset') + ->with($file, $designParams) + ->willReturn($asset); + + $pubDirectory = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $reflectionClass = new \ReflectionClass(Filter::class); + $reflectionProperty = $reflectionClass->getProperty('pubDirectory'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($filter, $pubDirectory); + $pubDirectory->expects($this->once()) + ->method('isExist') + ->with($path . DIRECTORY_SEPARATOR . $file) + ->willReturn(true); + $pubDirectory->expects($this->once()) + ->method('readFile') + ->with($path . DIRECTORY_SEPARATOR . $file) + ->willReturn($css); + + $filter->setDesignParams($designParams); + + $this->assertEquals($css, $filter->getCssFilesContent([$file])); + } + /** * @return array */ @@ -301,7 +372,19 @@ public function applyInlineCssDataProvider() */ public function testApplyInlineCssThrowsExceptionWhenDesignParamsNotSet() { - $this->getModel()->applyInlineCss('test'); + $filter = $this->getModel(); + $cssProcessor = $this->getMockBuilder(Processor::class) + ->disableOriginalConstructor() + ->getMock(); + $reflectionClass = new \ReflectionClass(Filter::class); + $reflectionProperty = $reflectionClass->getProperty('cssProcessor'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($filter, $cssProcessor); + $cssProcessor->expects($this->any()) + ->method('process') + ->willReturnArgument(0); + + $filter->applyInlineCss('test'); } /** @@ -348,7 +431,10 @@ public function testConfigDirectiveAvailable() $construction = ["{{config path={$path}}}", 'config', " path={$path}"]; $scopeConfigValue = 'value'; - $storeMock = $this->getMock('Magento\Store\Api\Data\StoreInterface', [], [], '', false); + $storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock); $storeMock->expects($this->once())->method('getId')->willReturn(1); @@ -369,7 +455,9 @@ public function testConfigDirectiveUnavailable() $construction = ["{{config path={$path}}}", 'config', " path={$path}"]; $scopeConfigValue = ''; - $storeMock = $this->getMock('Magento\Store\Api\Data\StoreInterface', [], [], '', false); + $storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->getMock(); $this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock); $storeMock->expects($this->once())->method('getId')->willReturn(1); diff --git a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php index 6b00b6069667a..189734260d0cb 100644 --- a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php @@ -1,6 +1,6 @@ [ 'templateType' => 'text', - 'templateText' => '', + 'templateText' => '', 'parsedTemplateText' => '', 'expectedTemplateSubject' => null, 'expectedOrigTemplateVariables' => null, @@ -312,7 +312,7 @@ public function loadDefaultDataProvider() ], 'copyright in HTML Removed' => [ 'templateType' => 'html', - 'templateText' => '', + 'templateText' => '', 'parsedTemplateText' => '', 'expectedTemplateSubject' => null, 'expectedOrigTemplateVariables' => null, diff --git a/app/code/Magento/Email/composer.json b/app/code/Magento/Email/composer.json index 6a930253466cb..0ccfe00b4f744 100644 --- a/app/code/Magento/Email/composer.json +++ b/app/code/Magento/Email/composer.json @@ -2,7 +2,8 @@ "name": "magento/module-email", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", + "magento/module-theme": "100.1.*", "magento/module-config": "100.1.*", "magento/module-store": "100.1.*", "magento/module-cms": "101.0.*", @@ -11,7 +12,7 @@ "magento/framework": "100.1.*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Email/etc/acl.xml b/app/code/Magento/Email/etc/acl.xml index 196cad452d87f..9d70af504cb79 100644 --- a/app/code/Magento/Email/etc/acl.xml +++ b/app/code/Magento/Email/etc/acl.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/etc/adminhtml/di.xml b/app/code/Magento/Email/etc/adminhtml/di.xml index 0d1730aeb174f..d276e099a3cdb 100644 --- a/app/code/Magento/Email/etc/adminhtml/di.xml +++ b/app/code/Magento/Email/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/etc/adminhtml/menu.xml b/app/code/Magento/Email/etc/adminhtml/menu.xml index 88de0d3712b82..74392027f8be7 100644 --- a/app/code/Magento/Email/etc/adminhtml/menu.xml +++ b/app/code/Magento/Email/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/etc/adminhtml/routes.xml b/app/code/Magento/Email/etc/adminhtml/routes.xml index d046727306240..ca44e51bdb419 100644 --- a/app/code/Magento/Email/etc/adminhtml/routes.xml +++ b/app/code/Magento/Email/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/etc/config.xml b/app/code/Magento/Email/etc/config.xml index 1b4063eaab294..ac1b27f737f8d 100644 --- a/app/code/Magento/Email/etc/config.xml +++ b/app/code/Magento/Email/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/etc/di.xml b/app/code/Magento/Email/etc/di.xml index 5be5efeb0b678..f23d296efc032 100644 --- a/app/code/Magento/Email/etc/di.xml +++ b/app/code/Magento/Email/etc/di.xml @@ -1,7 +1,7 @@ @@ -27,7 +27,7 @@ design/email/logo other_settings/email - Magento\Theme\Model\Design\Backend\Logo + Magento\Email\Model\Design\Backend\Logo media 1 diff --git a/app/code/Magento/Email/etc/email_templates.xml b/app/code/Magento/Email/etc/email_templates.xml index 8ae04e8f8d870..db40f8a4ea31b 100644 --- a/app/code/Magento/Email/etc/email_templates.xml +++ b/app/code/Magento/Email/etc/email_templates.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/etc/email_templates.xsd b/app/code/Magento/Email/etc/email_templates.xsd index 1b76c112c9d95..0d0040804e324 100644 --- a/app/code/Magento/Email/etc/email_templates.xsd +++ b/app/code/Magento/Email/etc/email_templates.xsd @@ -3,7 +3,7 @@ /** * Format of merged email templates configuration * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> diff --git a/app/code/Magento/Email/etc/frontend/di.xml b/app/code/Magento/Email/etc/frontend/di.xml index efa8fdc2c954d..c3a5c47605156 100644 --- a/app/code/Magento/Email/etc/frontend/di.xml +++ b/app/code/Magento/Email/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/etc/module.xml b/app/code/Magento/Email/etc/module.xml index 0c3262ff0e75a..eb2b5cdf25a74 100644 --- a/app/code/Magento/Email/etc/module.xml +++ b/app/code/Magento/Email/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/registration.php b/app/code/Magento/Email/registration.php index bd8a577077028..0a8cf96b09cc4 100644 --- a/app/code/Magento/Email/registration.php +++ b/app/code/Magento/Email/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml index f5411da7ff4c2..5a5cd07e99c66 100644 --- a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml +++ b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_grid_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_index.xml b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_index.xml index 2fe95e1279a5f..66638e24af575 100644 --- a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_index.xml +++ b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml index 7cf8aa41675ab..47bdaf01809f0 100644 --- a/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml +++ b/app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml b/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml index 26a70c64188a9..d91d085b7d784 100644 --- a/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml +++ b/app/code/Magento/Email/view/adminhtml/templates/template/edit.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Email/view/frontend/email/footer.html b/app/code/Magento/Email/view/frontend/email/footer.html index af97c24bacd69..e877e29bda5ab 100644 --- a/app/code/Magento/Email/view/frontend/email/footer.html +++ b/app/code/Magento/Email/view/frontend/email/footer.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Email/view/frontend/email/header.html b/app/code/Magento/Email/view/frontend/email/header.html index 09b6b155d639c..c86cbab461f71 100644 --- a/app/code/Magento/Email/view/frontend/email/header.html +++ b/app/code/Magento/Email/view/frontend/email/header.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/EncryptionKey/Block/Adminhtml/Crypt/Key/Edit.php b/app/code/Magento/EncryptionKey/Block/Adminhtml/Crypt/Key/Edit.php index a79257a965fbf..3386dd95d604e 100644 --- a/app/code/Magento/EncryptionKey/Block/Adminhtml/Crypt/Key/Edit.php +++ b/app/code/Magento/EncryptionKey/Block/Adminhtml/Crypt/Key/Edit.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/EncryptionKey/etc/adminhtml/menu.xml b/app/code/Magento/EncryptionKey/etc/adminhtml/menu.xml index e06fd7c57d517..71a0ff5470158 100644 --- a/app/code/Magento/EncryptionKey/etc/adminhtml/menu.xml +++ b/app/code/Magento/EncryptionKey/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/EncryptionKey/etc/adminhtml/routes.xml b/app/code/Magento/EncryptionKey/etc/adminhtml/routes.xml index f01babac19953..89ee76a7e3b81 100644 --- a/app/code/Magento/EncryptionKey/etc/adminhtml/routes.xml +++ b/app/code/Magento/EncryptionKey/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/EncryptionKey/etc/config.xml b/app/code/Magento/EncryptionKey/etc/config.xml index 92847ba864132..25a789115d997 100644 --- a/app/code/Magento/EncryptionKey/etc/config.xml +++ b/app/code/Magento/EncryptionKey/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/EncryptionKey/etc/module.xml b/app/code/Magento/EncryptionKey/etc/module.xml index 36688aeaa8ef1..5c4d2a35219aa 100644 --- a/app/code/Magento/EncryptionKey/etc/module.xml +++ b/app/code/Magento/EncryptionKey/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/EncryptionKey/registration.php b/app/code/Magento/EncryptionKey/registration.php index 69f7efd16802d..bcb8f627b4bca 100644 --- a/app/code/Magento/EncryptionKey/registration.php +++ b/app/code/Magento/EncryptionKey/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Fedex/Model/Carrier.php b/app/code/Magento/Fedex/Model/Carrier.php index 2d9e162d85f1c..0f7a8778cb50e 100644 --- a/app/code/Magento/Fedex/Model/Carrier.php +++ b/app/code/Magento/Fedex/Model/Carrier.php @@ -1,6 +1,6 @@ + * @author Magento Core Team * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -77,7 +78,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C /** * Rate result data * - * @var Result|null + * @var Result|TrackingResult */ protected $_result = null; @@ -126,6 +127,18 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C 'Key', 'Password', 'MeterNumber' ]; + /** + * Version of tracking service + * @var int + */ + private static $trackServiceVersion = 10; + + /** + * List of TrackReply errors + * @var array + */ + private static $trackingErrors = ['FAILURE', 'ERROR']; + /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory @@ -193,7 +206,7 @@ public function __construct( $wsdlBasePath = $configReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Fedex') . '/wsdl/'; $this->_shipServiceWsdl = $wsdlBasePath . 'ShipService_v10.wsdl'; $this->_rateServiceWsdl = $wsdlBasePath . 'RateService_v10.wsdl'; - $this->_trackServiceWsdl = $wsdlBasePath . 'TrackService_v5.wsdl'; + $this->_trackServiceWsdl = $wsdlBasePath . 'TrackService_v' . self::$trackServiceVersion . '.wsdl'; } /** @@ -338,6 +351,10 @@ public function setRequest(RateRequest $request) } else { } + if ($request->getDestCity()) { + $r->setDestCity($request->getDestCity()); + } + $weight = $this->getTotalNumOfBoxes($request->getPackageWeight()); $r->setWeight($weight); if ($request->getFreeMethodWeight() != $request->getPackageWeight()) { @@ -363,10 +380,13 @@ public function setRequest(RateRequest $request) /** * Get result of request * - * @return Result|null + * @return Result|TrackingResult */ public function getResult() { + if (!$this->_result) { + $this->_result = $this->_rateFactory->create(); + } return $this->_result; } @@ -432,6 +452,10 @@ protected function _formRateRequest($purpose) ], ]; + if ($r->getDestCity()) { + $ratesRequest['RequestedShipment']['Recipient']['Address']['City'] = $r->getDestCity(); + } + if ($purpose == self::RATE_REQUEST_GENERAL) { $ratesRequest['RequestedShipment']['RequestedPackageLineItems'][0]['InsuredValue'] = [ 'Amount' => $r->getValue(), @@ -1015,6 +1039,7 @@ protected function setTrackingReqeust() */ protected function _getXMLTracking($tracking) { + $this->_result = $this->_trackFactory->create(); $trackRequest = [ 'WebAuthenticationDetail' => [ 'UserCredential' => [ @@ -1026,9 +1051,16 @@ protected function _getXMLTracking($tracking) 'AccountNumber' => $this->getConfigData('account'), 'MeterNumber' => $this->getConfigData('meter_number'), ], - 'Version' => ['ServiceId' => 'trck', 'Major' => '5', 'Intermediate' => '0', 'Minor' => '0'], - 'PackageIdentifier' => ['Type' => 'TRACKING_NUMBER_OR_DOORTAG', 'Value' => $tracking], - 'IncludeDetailedScans' => 1, + 'Version' => [ + 'ServiceId' => 'trck', + 'Major' => self::$trackServiceVersion, + 'Intermediate' => '0', + 'Minor' => '0', + ], + 'SelectionDetails' => [ + 'PackageIdentifier' => ['Type' => 'TRACKING_NUMBER_OR_DOORTAG', 'Value' => $tracking], + ], + 'ProcessingOptions' => 'INCLUDE_DETAILED_SCANS' ]; $requestString = serialize($trackRequest); $response = $this->_getCachedQuotes($requestString); @@ -1055,114 +1087,48 @@ protected function _getXMLTracking($tracking) /** * Parse tracking response * - * @param string[] $trackingValue + * @param string $trackingValue * @param \stdClass $response * @return void - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ protected function _parseTrackingResponse($trackingValue, $response) { - if (is_object($response)) { - if ($response->HighestSeverity == 'FAILURE' || $response->HighestSeverity == 'ERROR') { - $errorTitle = (string)$response->Notifications->Message; - } elseif (isset($response->TrackDetails)) { - $trackInfo = $response->TrackDetails; - $resultArray['status'] = (string)$trackInfo->StatusDescription; - $resultArray['service'] = (string)$trackInfo->ServiceInfo; - $timestamp = isset( - $trackInfo->EstimatedDeliveryTimestamp - ) ? $trackInfo->EstimatedDeliveryTimestamp : $trackInfo->ActualDeliveryTimestamp; - $timestamp = strtotime((string)$timestamp); - if ($timestamp) { - $resultArray['deliverydate'] = date('Y-m-d', $timestamp); - $resultArray['deliverytime'] = date('H:i:s', $timestamp); - } - - $deliveryLocation = isset( - $trackInfo->EstimatedDeliveryAddress - ) ? $trackInfo->EstimatedDeliveryAddress : $trackInfo->ActualDeliveryAddress; - $deliveryLocationArray = []; - if (isset($deliveryLocation->City)) { - $deliveryLocationArray[] = (string)$deliveryLocation->City; - } - if (isset($deliveryLocation->StateOrProvinceCode)) { - $deliveryLocationArray[] = (string)$deliveryLocation->StateOrProvinceCode; - } - if (isset($deliveryLocation->CountryCode)) { - $deliveryLocationArray[] = (string)$deliveryLocation->CountryCode; - } - if ($deliveryLocationArray) { - $resultArray['deliverylocation'] = implode(', ', $deliveryLocationArray); - } - - $resultArray['signedby'] = (string)$trackInfo->DeliverySignatureName; - $resultArray['shippeddate'] = date('Y-m-d', (int)$trackInfo->ShipTimestamp); - if (isset($trackInfo->PackageWeight) && isset($trackInfo->Units)) { - $weight = (string)$trackInfo->PackageWeight; - $unit = (string)$trackInfo->Units; - $resultArray['weight'] = "{$weight} {$unit}"; - } - - $packageProgress = []; - if (isset($trackInfo->Events)) { - $events = $trackInfo->Events; - if (isset($events->Address)) { - $events = [$events]; - } - foreach ($events as $event) { - $tempArray = []; - $tempArray['activity'] = (string)$event->EventDescription; - $timestamp = strtotime((string)$event->Timestamp); - if ($timestamp) { - $tempArray['deliverydate'] = date('Y-m-d', $timestamp); - $tempArray['deliverytime'] = date('H:i:s', $timestamp); - } - if (isset($event->Address)) { - $addressArray = []; - $address = $event->Address; - if (isset($address->City)) { - $addressArray[] = (string)$address->City; - } - if (isset($address->StateOrProvinceCode)) { - $addressArray[] = (string)$address->StateOrProvinceCode; - } - if (isset($address->CountryCode)) { - $addressArray[] = (string)$address->CountryCode; - } - if ($addressArray) { - $tempArray['deliverylocation'] = implode(', ', $addressArray); - } - } - $packageProgress[] = $tempArray; - } - } - - $resultArray['progressdetail'] = $packageProgress; - } + if (!is_object($response) || empty($response->HighestSeverity)) { + $this->appendTrackingError($trackingValue, __('Invalid response from carrier')); + return; + } elseif (in_array($response->HighestSeverity, self::$trackingErrors)) { + $this->appendTrackingError($trackingValue, (string) $response->Notifications->Message); + return; + } elseif (empty($response->CompletedTrackDetails) || empty($response->CompletedTrackDetails->TrackDetails)) { + $this->appendTrackingError($trackingValue, __('No available tracking items')); + return; } - if (!$this->_result) { - $this->_result = $this->_trackFactory->create(); + $trackInfo = $response->CompletedTrackDetails->TrackDetails; + + // Fedex can return tracking details as single object instead array + if (is_object($trackInfo)) { + $trackInfo = [$trackInfo]; } - if (isset($resultArray)) { + $result = $this->getResult(); + $carrierTitle = $this->getConfigData('title'); + $counter = 0; + foreach ($trackInfo as $item) { $tracking = $this->_trackStatusFactory->create(); - $tracking->setCarrier('fedex'); - $tracking->setCarrierTitle($this->getConfigData('title')); + $tracking->setCarrier(self::CODE); + $tracking->setCarrierTitle($carrierTitle); $tracking->setTracking($trackingValue); - $tracking->addData($resultArray); - $this->_result->append($tracking); - } else { - $error = $this->_trackErrorFactory->create(); - $error->setCarrier('fedex'); - $error->setCarrierTitle($this->getConfigData('title')); - $error->setTracking($trackingValue); - $error->setErrorMessage( - $errorTitle ? $errorTitle : __('For some reason we can\'t retrieve tracking info right now.') + $tracking->addData($this->processTrackingDetails($item)); + $result->append($tracking); + $counter ++; + } + + // no available tracking details + if (!$counter) { + $this->appendTrackingError( + $trackingValue, __('For some reason we can\'t retrieve tracking info right now.') ); - $this->_result->append($error); } } @@ -1586,4 +1552,171 @@ protected function filterDebugData($data) } return $data; } + + /** + * Parse track details response from Fedex + * @param \stdClass $trackInfo + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + + @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function processTrackingDetails(\stdClass $trackInfo) + { + $result = [ + 'shippeddate' => null, + 'deliverydate' => null, + 'deliverytime' => null, + 'deliverylocation' => null, + 'weight' => null, + 'progressdetail' => [], + ]; + + if (!empty($trackInfo->ShipTimestamp) && + ($datetime = \DateTime::createFromFormat(\DateTime::ISO8601, $trackInfo->ShipTimestamp)) !== false + ) { + $result['shippeddate'] = $datetime->format('Y-m-d'); + } + + $result['signedby'] = !empty($trackInfo->DeliverySignatureName) ? + (string) $trackInfo->DeliverySignatureName : + null; + + $result['status'] = (!empty($trackInfo->StatusDetail) && !empty($trackInfo->StatusDetail->Description)) ? + (string) $trackInfo->StatusDetail->Description : + null; + $result['service'] = (!empty($trackInfo->Service) && !empty($trackInfo->Service->Description)) ? + (string) $trackInfo->Service->Description : + null; + + $datetime = $this->getDeliveryDateTime($trackInfo); + if ($datetime) { + $result['deliverydate'] = $datetime->format('Y-m-d'); + $result['deliverytime'] = $datetime->format('H:i:s'); + } + + $address = null; + if (!empty($trackInfo->EstimatedDeliveryAddress)) { + $address = $trackInfo->EstimatedDeliveryAddress; + } elseif (!empty($trackInfo->ActualDeliveryAddress)) { + $address = $trackInfo->ActualDeliveryAddress; + } + + if (!empty($address)) { + $result['deliverylocation'] = $this->getDeliveryAddress($address); + } + + if (!empty($trackInfo->PackageWeight)) { + $result['weight'] = sprintf( + '%s %s', + (string) $trackInfo->PackageWeight->Value, + (string) $trackInfo->PackageWeight->Units + ); + } + + if (!empty($trackInfo->Events)) { + $events = $trackInfo->Events; + if (is_object($events)) { + $events = [$trackInfo->Events]; + } + $result['progressdetail'] = $this->processTrackDetailsEvents($events); + } + + return $result; + } + + /** + * Parse delivery datetime from tracking details + * @param \stdClass $trackInfo + * @return \Datetime|null + */ + private function getDeliveryDateTime(\stdClass $trackInfo) + { + $timestamp = null; + if (!empty($trackInfo->EstimatedDeliveryTimestamp)) { + $timestamp = $trackInfo->EstimatedDeliveryTimestamp; + } elseif (!empty($trackInfo->ActualDeliveryTimestamp)) { + $timestamp = $trackInfo->ActualDeliveryTimestamp; + } + + return $timestamp ? \DateTime::createFromFormat(\DateTime::ISO8601, $timestamp) : null; + } + + /** + * Get delivery address details in string representation + * Return City, State, Country Code + * + * @param \stdClass $address + * @return string + */ + private function getDeliveryAddress(\stdClass $address) + { + $details = []; + + if (!empty($address->City)) { + $details[] = (string) $address->City; + } + + if (!empty($address->StateOrProvinceCode)) { + $details[] = (string) $address->StateOrProvinceCode; + } + + if (!empty($address->CountryCode)) { + $details[] = (string) $address->CountryCode; + } + + return implode(', ', $details); + } + + /** + * Parse tracking details events from response + * Return list of items in such format: + * ['activity', 'deliverydate', 'deliverytime', 'deliverylocation'] + * + * @param array $events + * @return array + */ + private function processTrackDetailsEvents(array $events) + { + $result = []; + /** @var \stdClass $event */ + foreach ($events as $event) { + $item = [ + 'activity' => (string) $event->EventDescription, + 'deliverydate' => null, + 'deliverytime' => null, + 'deliverylocation' => null + ]; + + if (!empty($event->Timestamp)) { + $datetime = \DateTime::createFromFormat(\DateTime::ISO8601, $event->Timestamp); + $item['deliverydate'] = $datetime->format('Y-m-d'); + $item['deliverytime'] = $datetime->format('H:i:s'); + } + + if (!empty($event->Address)) { + $item['deliverylocation'] = $this->getDeliveryAddress($event->Address); + } + + $result[] = $item; + } + + return $result; + } + + /** + * Append error message to rate result instance + * @param string $trackingValue + * @param string $errorMessage + * @return void + */ + private function appendTrackingError($trackingValue, $errorMessage) + { + $error = $this->_trackErrorFactory->create(); + $error->setCarrier(self::CODE); + $error->setCarrierTitle($this->getConfigData('title')); + $error->setTracking($trackingValue); + $error->setErrorMessage($errorMessage); + $result = $this->getResult(); + $result->append($error); + } } diff --git a/app/code/Magento/Fedex/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php b/app/code/Magento/Fedex/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php index 7319a6e9e694c..ccf80727d697a 100644 --- a/app/code/Magento/Fedex/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php +++ b/app/code/Magento/Fedex/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php @@ -1,6 +1,6 @@ scope = $this->getMockBuilder( - '\Magento\Framework\App\Config\ScopeConfigInterface' - )->disableOriginalConstructor()->getMock(); - - $this->scope->expects( - $this->any() - )->method( - 'getValue' - )->will( - $this->returnCallback([$this, 'scopeConfiggetValue']) - ); - - $country = $this->getMock( - 'Magento\Directory\Model\Country', - ['load', 'getData', '__wakeup'], - [], - '', - false - ); - $country->expects($this->any())->method('load')->will($this->returnSelf()); - $countryFactory = $this->getMock('Magento\Directory\Model\CountryFactory', ['create'], [], '', false); - $countryFactory->expects($this->any())->method('create')->will($this->returnValue($country)); - - $rate = $this->getMock('Magento\Shipping\Model\Rate\Result', ['getError'], [], '', false); - $rateFactory = $this->getMock('Magento\Shipping\Model\Rate\ResultFactory', ['create'], [], '', false); - $rateFactory->expects($this->any())->method('create')->will($this->returnValue($rate)); - - $this->error = $this->getMockBuilder('\Magento\Quote\Model\Quote\Address\RateResult\Error') - ->setMethods(['setCarrier', 'setCarrierTitle', 'setErrorMessage']) + $this->helper = new ObjectManager($this); + $this->scope = $this->getMockBuilder(ScopeConfigInterface::class) + ->disableOriginalConstructor() ->getMock(); - $this->errorFactory = $this->getMockBuilder('Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory') + + $this->scope->expects(static::any()) + ->method('getValue') + ->willReturnCallback([$this, 'scopeConfigGetValue']); + + $countryFactory = $this->getCountryFactory(); + $rateFactory = $this->getRateFactory(); + $storeManager = $this->getStoreManager(); + $resultFactory = $this->getResultFactory(); + $this->initRateErrorFactory(); + + $rateMethodFactory = $this->getRateMethodFactory(); + + $this->trackErrorFactory = $this->getMockBuilder(ErrorFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->errorFactory->expects($this->any())->method('create')->willReturn($this->error); - - $store = $this->getMock('Magento\Store\Model\Store', ['getBaseCurrencyCode', '__wakeup'], [], '', false); - $storeManager = $this->getMockForAbstractClass('Magento\Store\Model\StoreManagerInterface'); - $storeManager->expects($this->any())->method('getStore')->will($this->returnValue($store)); - $priceCurrency = $this->getMockBuilder('Magento\Framework\Pricing\PriceCurrencyInterface')->getMock(); - - $rateMethod = $this->getMock( - 'Magento\Quote\Model\Quote\Address\RateResult\Method', - null, - ['priceCurrency' => $priceCurrency] - ); - $rateMethodFactory = $this->getMock( - 'Magento\Quote\Model\Quote\Address\RateResult\MethodFactory', - ['create'], - [], - '', - false - ); - $rateMethodFactory->expects($this->any())->method('create')->will($this->returnValue($rateMethod)); - $this->_model = $this->getMock( - 'Magento\Fedex\Model\Carrier', - ['_getCachedQuotes', '_debug'], - [ - 'scopeConfig' => $this->scope, - 'rateErrorFactory' => $this->errorFactory, - 'logger' => $this->getMock('Psr\Log\LoggerInterface'), - 'xmlSecurity' => new Security(), - 'xmlElFactory' => $this->getMock('Magento\Shipping\Model\Simplexml\ElementFactory', [], [], '', false), - 'rateFactory' => $rateFactory, - 'rateMethodFactory' => $rateMethodFactory, - 'trackFactory' => $this->getMock('Magento\Shipping\Model\Tracking\ResultFactory', [], [], '', false), - 'trackErrorFactory' => - $this->getMock('Magento\Shipping\Model\Tracking\Result\ErrorFactory', [], [], '', false), - 'trackStatusFactory' => - $this->getMock('Magento\Shipping\Model\Tracking\Result\StatusFactory', [], [], '', false), - 'regionFactory' => $this->getMock('Magento\Directory\Model\RegionFactory', [], [], '', false), - 'countryFactory' => $countryFactory, - 'currencyFactory' => $this->getMock('Magento\Directory\Model\CurrencyFactory', [], [], '', false), - 'directoryData' => $this->getMock('Magento\Directory\Helper\Data', [], [], '', false), - 'stockRegistry' => $this->getMock('Magento\CatalogInventory\Model\StockRegistry', [], [], '', false), - 'storeManager' => $storeManager, - 'configReader' => $this->getMock('Magento\Framework\Module\Dir\Reader', [], [], '', false), - 'productCollectionFactory' => - $this->getMock('Magento\Catalog\Model\ResourceModel\Product\CollectionFactory', [], [], '', false), - 'data' => [] - ] - ); + + $this->statusFactory = $this->getMockBuilder(StatusFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $elementFactory = $this->getMockBuilder(ElementFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $collectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $regionFactory = $this->getMockBuilder(RegionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $currencyFactory = $this->getMockBuilder(CurrencyFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $data = $this->getMockBuilder(Data::class) + ->disableOriginalConstructor() + ->getMock(); + + $stockRegistry = $this->getMockBuilder(StockRegistry::class) + ->disableOriginalConstructor() + ->getMock(); + + $reader = $this->getMockBuilder(Reader::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = $this->getMockBuilder(Carrier::class) + ->setMethods(['_getCachedQuotes', '_debug']) + ->setConstructorArgs( + [ + 'scopeConfig' => $this->scope, + 'rateErrorFactory' => $this->errorFactory, + 'logger' => $this->getMock(LoggerInterface::class), + 'xmlSecurity' => new Security(), + 'xmlElFactory' => $elementFactory, + 'rateFactory' => $rateFactory, + 'rateMethodFactory' => $rateMethodFactory, + 'trackFactory' => $resultFactory, + 'trackErrorFactory' => $this->trackErrorFactory, + 'trackStatusFactory' => $this->statusFactory, + 'regionFactory' => $regionFactory, + 'countryFactory' => $countryFactory, + 'currencyFactory' => $currencyFactory, + 'directoryData' => $data, + 'stockRegistry' => $stockRegistry, + 'storeManager' => $storeManager, + 'configReader' => $reader, + 'productCollectionFactory' => $collectionFactory, + ] + ) + ->getMock(); + } + + public function testSetRequestWithoutCity() + { + $requestMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\RateRequest::class) + ->disableOriginalConstructor() + ->setMethods(['getDestCity']) + ->getMock(); + $requestMock->expects($this->once()) + ->method('getDestCity') + ->willReturn(null); + $this->model->setRequest($requestMock); + } + + public function testSetRequestWithCity() + { + $requestMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\RateRequest::class) + ->disableOriginalConstructor() + ->setMethods(['getDestCity']) + ->getMock(); + $requestMock->expects($this->exactly(2)) + ->method('getDestCity') + ->willReturn('Small Town'); + $this->model->setRequest($requestMock); } /** @@ -138,7 +200,7 @@ protected function setUp() * @param $path * @return null|string */ - public function scopeConfiggetValue($path) + public function scopeConfigGetValue($path) { switch ($path) { case 'carriers/fedex/showmethod': @@ -148,44 +210,57 @@ public function scopeConfiggetValue($path) return 'ServiceType'; break; } + return null; } /** + * @param float $amount + * @param string $rateType + * @param float $expected * @dataProvider collectRatesDataProvider */ public function testCollectRatesRateAmountOriginBased($amount, $rateType, $expected) { - $this->scope->expects($this->any())->method('isSetFlag')->will($this->returnValue(true)); + $this->scope->expects(static::any()) + ->method('isSetFlag') + ->willReturn(true); // @codingStandardsIgnoreStart - $netAmount = new \Magento\Framework\DataObject([]); + $netAmount = new \stdClass(); $netAmount->Amount = $amount; - $totalNetCharge = new \Magento\Framework\DataObject([]); + $totalNetCharge = new \stdClass(); $totalNetCharge->TotalNetCharge = $netAmount; $totalNetCharge->RateType = $rateType; - $ratedShipmentDetail = new \Magento\Framework\DataObject([]); + $ratedShipmentDetail = new \stdClass(); $ratedShipmentDetail->ShipmentRateDetail = $totalNetCharge; - $rate = new \Magento\Framework\DataObject([]); + $rate = new \stdClass(); $rate->ServiceType = 'ServiceType'; $rate->RatedShipmentDetails = [$ratedShipmentDetail]; - $response = new \Magento\Framework\DataObject([]); + $response = new \stdClass(); $response->HighestSeverity = 'SUCCESS'; $response->RateReplyDetails = $rate; + // @codingStandardsIgnoreEnd - $this->_model->expects($this->any())->method('_getCachedQuotes')->will( - $this->returnValue(serialize($response)) - ); - $request = $this->getMock('Magento\Quote\Model\Quote\Address\RateRequest', [], [], '', false); - foreach ($this->_model->collectRates($request)->getAllRates() as $allRates) { + $this->model->expects(static::any()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + $request = $this->getMockBuilder(RateRequest::class) + ->disableOriginalConstructor() + ->getMock(); + + foreach ($this->model->collectRates($request)->getAllRates() as $allRates) { $this->assertEquals($expected, $allRates->getData('cost')); } - // @codingStandardsIgnoreEnd } + /** + * Get list of rates variations + * @return array + */ public function collectRatesDataProvider() { return [ @@ -202,16 +277,22 @@ public function collectRatesDataProvider() public function testCollectRatesErrorMessage() { - $this->scope->expects($this->once())->method('isSetFlag')->willReturn(false); + $this->scope->expects(static::once()) + ->method('isSetFlag') + ->willReturn(false); - $this->error->expects($this->once())->method('setCarrier')->with('fedex'); - $this->error->expects($this->once())->method('setCarrierTitle'); - $this->error->expects($this->once())->method('setErrorMessage'); + $this->error->expects(static::once()) + ->method('setCarrier') + ->with('fedex'); + $this->error->expects(static::once()) + ->method('setCarrierTitle'); + $this->error->expects(static::once()) + ->method('setErrorMessage'); $request = new RateRequest(); $request->setPackageWeight(1); - $this->assertSame($this->error, $this->_model->collectRates($request)); + static::assertSame($this->error, $this->model->collectRates($request)); } /** @@ -225,11 +306,11 @@ public function testFilterDebugData($data, array $maskFields, $expected) $refClass = new \ReflectionClass(Carrier::class); $property = $refClass->getProperty('_debugReplacePrivateDataKeys'); $property->setAccessible(true); - $property->setValue($this->_model, $maskFields); + $property->setValue($this->model, $maskFields); $refMethod = $refClass->getMethod('filterDebugData'); $refMethod->setAccessible(true); - $result = $refMethod->invoke($this->_model, $data); + $result = $refMethod->invoke($this->model, $data); static::assertEquals($expected, $result); } @@ -268,4 +349,301 @@ public function logDataProvider() ], ]; } + + /** + * @covers \Magento\Fedex\Model\Carrier::getTracking + */ + public function testGetTrackingErrorResponse() + { + $tracking = '123456789012'; + $errorMessage = 'Tracking information is unavailable.'; + + // @codingStandardsIgnoreStart + $response = new \stdClass(); + $response->HighestSeverity = 'ERROR'; + $response->Notifications = new \stdClass(); + $response->Notifications->Message = $errorMessage; + // @codingStandardsIgnoreEnd + + $this->model->expects(static::once()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + + $error = $this->helper->getObject(Error::class); + $this->trackErrorFactory->expects(static::once()) + ->method('create') + ->willReturn($error); + + $this->model->getTracking($tracking); + $tracks = $this->model->getResult()->getAllTrackings(); + + static::assertEquals(1, count($tracks)); + + /** @var Error $current */ + $current = $tracks[0]; + static::assertInstanceOf(Error::class, $current); + static::assertEquals(__($errorMessage), $current->getErrorMessage()); + } + + /** + * @covers \Magento\Fedex\Model\Carrier::getTracking + * @param string $shipTimestamp + * @param string $expectedDate + * @dataProvider shipDateDataProvider + */ + public function testGetTracking($shipTimestamp, $expectedDate) + { + $tracking = '123456789012'; + + // @codingStandardsIgnoreStart + $response = new \stdClass(); + $response->HighestSeverity = 'SUCCESS'; + $response->CompletedTrackDetails = new \stdClass(); + + $trackDetails = new \stdClass(); + $trackDetails->ShipTimestamp = $shipTimestamp; + $trackDetails->DeliverySignatureName = 'signature'; + + $trackDetails->StatusDetail = new \stdClass(); + $trackDetails->StatusDetail->Description = 'SUCCESS'; + + $trackDetails->Service = new \stdClass(); + $trackDetails->Service->Description = 'ground'; + $trackDetails->EstimatedDeliveryTimestamp = '2016-08-10T10:20:26+00:00'; + + $trackDetails->EstimatedDeliveryAddress = new \stdClass(); + $trackDetails->EstimatedDeliveryAddress->City = 'Culver City'; + $trackDetails->EstimatedDeliveryAddress->StateOrProvinceCode = 'CA'; + $trackDetails->EstimatedDeliveryAddress->CountryCode = 'US'; + + $trackDetails->PackageWeight = new \stdClass(); + $trackDetails->PackageWeight->Value = 23; + $trackDetails->PackageWeight->Units = 'LB'; + + $response->CompletedTrackDetails->TrackDetails = [$trackDetails]; + // @codingStandardsIgnoreEnd + + $this->model->expects(static::once()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + + $status = $this->helper->getObject(Status::class); + $this->statusFactory->expects(static::once()) + ->method('create') + ->willReturn($status); + + $this->model->getTracking($tracking); + $tracks = $this->model->getResult()->getAllTrackings(); + static::assertEquals(1, count($tracks)); + + $current = $tracks[0]; + $fields = [ + 'signedby', + 'status', + 'service', + 'deliverydate', + 'deliverytime', + 'deliverylocation', + 'weight', + ]; + array_walk($fields, function ($field) use ($current) { + static::assertNotEmpty($current[$field]); + }); + + static::assertEquals('2016-08-10', $current['deliverydate']); + static::assertEquals('10:20:26', $current['deliverytime']); + static::assertEquals($expectedDate, $current['shippeddate']); + } + + /** + * Get list of variations for testing ship date + * @return array + */ + public function shipDateDataProvider() + { + return [ + ['shipTimestamp' => '2016-08-05T14:06:35+00:00', 'expectedDate' => '2016-08-05'], + ['shipTimestamp' => '2016-08-05T14:06:35', 'expectedDate' => null], + ['shipTimestamp' => '2016-08-05 14:06:35', 'expectedDate' => null], + ['shipTimestamp' => '2016-08-05 14:06:35+00:00', 'expectedDate' => null], + ['shipTimestamp' => '2016-08-05', 'expectedDate' => null], + ['shipTimestamp' => '2016/08/05', 'expectedDate' => null], + ]; + } + + /** + * @covers \Magento\Fedex\Model\Carrier::getTracking + */ + public function testGetTrackingWithEvents() + { + $tracking = '123456789012'; + + // @codingStandardsIgnoreStart + $response = new \stdClass(); + $response->HighestSeverity = 'SUCCESS'; + $response->CompletedTrackDetails = new \stdClass(); + + $event = new \stdClass(); + $event->EventDescription = 'Test'; + $event->Timestamp = '2016-08-05T19:14:53+00:00'; + $event->Address = new \stdClass(); + + $event->Address->City = 'Culver City'; + $event->Address->StateOrProvinceCode = 'CA'; + $event->Address->CountryCode = 'US'; + + $trackDetails = new \stdClass(); + $trackDetails->Events = $event; + + $response->CompletedTrackDetails->TrackDetails = $trackDetails; + // @codingStandardsIgnoreEnd + + $this->model->expects(static::once()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + + $status = $this->helper->getObject(Status::class); + $this->statusFactory->expects(static::once()) + ->method('create') + ->willReturn($status); + + $this->model->getTracking($tracking); + $tracks = $this->model->getResult()->getAllTrackings(); + static::assertEquals(1, count($tracks)); + + $current = $tracks[0]; + static::assertNotEmpty($current['progressdetail']); + static::assertEquals(1, count($current['progressdetail'])); + + $event = $current['progressdetail'][0]; + $fields = ['activity', 'deliverydate', 'deliverytime', 'deliverylocation']; + array_walk($fields, function ($field) use ($event) { + static::assertNotEmpty($event[$field]); + }); + static::assertEquals('2016-08-05', $event['deliverydate']); + static::assertEquals('19:14:53', $event['deliverytime']); + } + + /** + * Init RateErrorFactory and RateResultErrors mocks + * @return void + */ + private function initRateErrorFactory() + { + $this->error = $this->getMockBuilder(RateResultError::class) + ->disableOriginalConstructor() + ->setMethods(['setCarrier', 'setCarrierTitle', 'setErrorMessage']) + ->getMock(); + $this->errorFactory = $this->getMockBuilder(RateErrorFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->errorFactory->expects(static::any()) + ->method('create') + ->willReturn($this->error); + } + + /** + * Creates mock rate result factory + * @return RateResultFactory|MockObject + */ + private function getRateFactory() + { + $rate = $this->getMockBuilder(RateResult::class) + ->disableOriginalConstructor() + ->setMethods(['getError']) + ->getMock(); + $rateFactory = $this->getMockBuilder(RateResultFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $rateFactory->expects(static::any()) + ->method('create') + ->willReturn($rate); + + return $rateFactory; + } + + /** + * Creates mock object for CountryFactory class + * @return CountryFactory|MockObject + */ + private function getCountryFactory() + { + $country = $this->getMockBuilder(Country::class) + ->disableOriginalConstructor() + ->setMethods(['load', 'getData']) + ->getMock(); + $country->expects(static::any()) + ->method('load') + ->willReturnSelf(); + + $countryFactory = $this->getMockBuilder(CountryFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $countryFactory->expects(static::any()) + ->method('create') + ->willReturn($country); + + return $countryFactory; + } + + /** + * Creates mock object for ResultFactory class + * @return ResultFactory|MockObject + */ + private function getResultFactory() + { + $resultFactory = $this->getMockBuilder(ResultFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->result = $this->helper->getObject(Result::class); + $resultFactory->expects(static::any()) + ->method('create') + ->willReturn($this->result); + + return $resultFactory; + } + + /** + * Creates mock object for store manager + * @return StoreManagerInterface|MockObject + */ + private function getStoreManager() + { + $store = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getBaseCurrencyCode']) + ->getMock(); + $storeManager = $this->getMock(StoreManagerInterface::class); + $storeManager->expects(static::any()) + ->method('getStore') + ->willReturn($store); + + return $storeManager; + } + + /** + * Creates mock object for rate method factory + * @return MethodFactory|MockObject + */ + private function getRateMethodFactory() + { + $priceCurrency = $this->getMock(PriceCurrencyInterface::class); + $rateMethod = $this->getMockBuilder(Method::class) + ->setConstructorArgs(['priceCurrency' => $priceCurrency]) + ->setMethods(null) + ->getMock(); + $rateMethodFactory = $this->getMockBuilder(MethodFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $rateMethodFactory->expects(static::any()) + ->method('create') + ->willReturn($rateMethod); + + return $rateMethodFactory; + } } diff --git a/app/code/Magento/Fedex/composer.json b/app/code/Magento/Fedex/composer.json index f25ed20625c8c..4923bdb740d20 100644 --- a/app/code/Magento/Fedex/composer.json +++ b/app/code/Magento/Fedex/composer.json @@ -2,7 +2,7 @@ "name": "magento/module-fedex", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/module-store": "100.1.*", "magento/module-shipping": "100.1.*", "magento/module-directory": "100.1.*", @@ -15,7 +15,7 @@ "lib-libxml": "*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Fedex/etc/adminhtml/system.xml b/app/code/Magento/Fedex/etc/adminhtml/system.xml index 1de61c2c15494..7e00f9c10035c 100644 --- a/app/code/Magento/Fedex/etc/adminhtml/system.xml +++ b/app/code/Magento/Fedex/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Fedex/etc/config.xml b/app/code/Magento/Fedex/etc/config.xml index d3dc876d670aa..0e7a178fe504b 100644 --- a/app/code/Magento/Fedex/etc/config.xml +++ b/app/code/Magento/Fedex/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Fedex/etc/di.xml b/app/code/Magento/Fedex/etc/di.xml index 454beffacba9d..e03931a35472d 100644 --- a/app/code/Magento/Fedex/etc/di.xml +++ b/app/code/Magento/Fedex/etc/di.xml @@ -1,7 +1,7 @@ @@ -10,4 +10,14 @@ + + + + 1 + 1 + 1 + 1 + + + diff --git a/app/code/Magento/Fedex/etc/module.xml b/app/code/Magento/Fedex/etc/module.xml index af58dd2e800ab..f435c72c601b9 100644 --- a/app/code/Magento/Fedex/etc/module.xml +++ b/app/code/Magento/Fedex/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Fedex/etc/wsdl/TrackService_v5.wsdl b/app/code/Magento/Fedex/etc/wsdl/TrackService_v10.wsdl similarity index 63% rename from app/code/Magento/Fedex/etc/wsdl/TrackService_v5.wsdl rename to app/code/Magento/Fedex/etc/wsdl/TrackService_v10.wsdl index f3ceaf5056a20..cfd3a46386df2 100644 --- a/app/code/Magento/Fedex/etc/wsdl/TrackService_v5.wsdl +++ b/app/code/Magento/Fedex/etc/wsdl/TrackService_v10.wsdl @@ -1,12 +1,12 @@ - + - + + + - - @@ -14,7 +14,7 @@ Descriptive data for a physical location. May be used as an actual physical address (place to which one could go), or as a container of "address parts" which should be handled as a unit (such as a city-state-ZIP combination within the US). - + Combination of number, street name, etc. At least one line is required for a valid physical address; empty lines should not be included. @@ -44,6 +44,11 @@ The two-letter code used to identify a country. + + + The fully spelt out name of a country. + + Indicates whether this address residential (as opposed to commercial). @@ -51,6 +56,48 @@ + + + Specifies the different appointment times on a specific date. + + + + + + Different appointment time windows on the date specified. + + + + + + + Specifies the details about the appointment time window. + + + + + The description that FedEx Ground uses for the appointment window being specified. + + + + + Specifies the window of time for an appointment. + + + + + + + + The description that FedEx uses for a given appointment window. + + + + + + + + Identifies where a tracking event occurs. @@ -73,11 +120,18 @@ + + + + + + + Identification of a FedEx operating company (transportation). @@ -108,7 +162,7 @@ - Only used in transactions which require identification of the Fed Ex Office integrator. + Only used in transactions which require identification of the FedEx Office integrator. @@ -118,6 +172,75 @@ + + + + + Value used to identify a commodity description; must be unique within the containing shipment. + + + + + + + + + + + + + Contains only additional quantitative information other than weight and quantity to calculate duties and taxes. + + + + + + + Defines additional characteristic of commodity used to calculate duties and taxes + + + + + + + + + All data required for this commodity in NAFTA Certificate of Origin. + + + + + + + + + + + True if duplicate packages (more than one package with the same tracking number) have been found, and only limited data will be provided for each one. + + + + + True if additional packages remain to be retrieved. + + + + + Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true). + + + + + Identifies the total number of available track details across all pages. + + + + + Contains detailed tracking information for the requested packages(s). + + + + The descriptive data for a point-of-contact person. @@ -148,6 +271,11 @@ Identifies the phone extension associated with this contact. + + + Identifies a toll free number, if any, associated with this contact. + + Identifies the pager number associated with this contact. @@ -171,6 +299,84 @@ + + + + + + + + + + + + + Unique identifier for the customer exception request. + + + + + + + + + + + + + Specifies additional description about customs options. This is a required field when the customs options type is "OTHER". + + + + + + + + + + + + + + + + + + + + + + + + + + + Details about the eligibility for a delivery option. + + + + + Type of delivery option. + + + + + Eligibility of the customer for the specific delivery option. + + + + + + + Specifies the different option types for delivery. + + + + + + + + The dimensions of this package and the unit type used for the measurements. @@ -280,6 +486,43 @@ + + + + + + Customer-declared value, with data type and legal values depending on excise condition, used in defining the taxable value of the item. + + + + + + + Specifies different values of eligibility status + + + + + + + + + + Identifies a kind of FedEx facility. + + + + + + + + + + + + + + CM = centimeters, IN = inches @@ -289,6 +532,15 @@ + + + Time Range specified in local time. + + + + + + Identifies the representation of human-readable text. @@ -306,6 +558,73 @@ + + + + + + + + + + + + + + + + + Defined by NAFTA regulations. + + + + + Defined by NAFTA regulations. + + + + + Identification of which producer is associated with this commodity (if multiple producers are used in a single shipment). + + + + + + Date range over which RVC net cost was calculated. + + + + + + + + + + + + + See instructions for NAFTA Certificate of Origin for code definitions. + + + + + + + + + + + + + See instructions for NAFTA Certificate of Origin for code definitions. + + + + + + + + The descriptive data regarding the result of the submitted transaction. @@ -382,7 +701,18 @@ Identification for a FedEx operating company (transportation and non-transportation). + + + + + + + + + + + @@ -394,11 +724,42 @@ + + + + + + + + + When the MoreData field = true in a TrackReply the PagingToken must be sent in the subsequent TrackRequest to retrieve the next page of data. + + + + + Specifies the number of results to display per page when the there is more than one page in the subsequent TrackReply. + + + + + + + + + + + + + + + + + Tracking number and additional shipment data used to identify a unique shipment for proof of delivery. @@ -431,13 +792,115 @@ - - - - - - - + + + + + This contains the severity type of the most severe Notification in the Notifications array. + + + + + Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply. + + + + + Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data. + + + + + Contains the version of the reply being used. + + + + + True if duplicate packages (more than one package with the same tracking number) have been found, the packages array contains information about each duplicate. Use this information to determine which of the tracking numbers is the one you need and resend your request using the tracking number and TrackingNumberUniqueIdentifier for that package. + + + + + True if additional packages remain to be retrieved. + + + + + Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true). + + + + + Information about the notifications that are available for this tracking number. If there are duplicates the ship date and destination address information is returned for determining which TrackingNumberUniqueIdentifier to use on a subsequent request. + + + + + + + + + Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services). + + + + + Descriptive data identifying the client submitting the transaction. + + + + + Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations + + + + + + The tracking number to which the notifications will be triggered from. + + + + + Indicates whether to return tracking information for all associated packages. + + + + + When the MoreDataAvailable field is true in a TrackNotificationReply the PagingToken must be sent in the subsequent TrackNotificationRequest to retrieve the next page of data. + + + + + Use this field when your original request informs you that there are duplicates of this tracking number. If you get duplicates you will also receive some information about each of the duplicate tracking numbers to enable you to chose one and resend that number along with the TrackingNumberUniqueId to get notifications for that tracking number. + + + + + To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates. + + + + + To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates. + + + + + Included in the email notification identifying the requester of this notification. + + + + + Included in the email notification identifying the requester of this notification. + + + + + Who to send the email notifications to and for which events. The notificationRecipientType and NotifyOnShipment fields are not used in this request. + + + + The service type of the package/shipment. @@ -449,11 +912,34 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -465,10 +951,19 @@ + + + + + + + + + FedEx Signature Proof Of Delivery Fax reply. @@ -554,6 +1049,7 @@ + @@ -635,6 +1131,32 @@ + + + + + Specifies the status of the track special instructions requested. + + + + + Time when the status was changed. + + + + + + + + + + + + + + + + Each instance of this data type represents a barcode whose content must be represented as ASCII text (i.e. not binary data). @@ -662,22 +1184,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + The delivery location at the delivered to address. + + + + + + + + + + + + + + + + Detailed tracking information about a particular package. @@ -699,16 +1263,12 @@ When duplicate tracking numbers exist this data is returned with summary information for each of the duplicates. The summary information is used to determine which of the duplicates the intended tracking number is. This identifier is used on a subsequent track request to retrieve the tracking data for the desired tracking number. - + - A code that identifies this type of status. This is the most recent status. - - - - - A human-readable description of this status. + Specifies details about the status of the shipment being tracked. + Used to report the status of a piece of a multiple piece shipment which is no longer traveling with the rest of the packages in the shipment or has not been accounted for. @@ -719,6 +1279,8 @@ Used to convey information such as. 1. FedEx has received information about a package but has not yet taken possession of it. 2. FedEx has handed the package off to a third party for final delivery. 3. The package delivery has been cancelled + + Identifies a FedEx operating company (transportation). @@ -729,24 +1291,34 @@ Identifies operating transportation company that is the specific to the carrier code. + + + Specifies a detailed description about the carrier or the operating company. + + + + + If the package was interlined to a cartage agent, this is the name of the cartage agent. (Returned for CSR SL only.) + + Specifies the FXO production centre contact and address. - + Other related identifiers for this package such as reference numbers. - + - Retained for legacy compatibility only. User/screen friendly description of the Service type (e.g. Priority Overnight). + (Returned for CSR SL only.) - + - Strict representation of the Service type (e.g. PRIORITY_OVERNIGHT). + Specifies details about service such as service description and type. @@ -789,8 +1361,40 @@ The number of packages in this shipment. - - + + + Specifies the details about the SPOC details. + + + + + + + + + + + + + Specifies the reason for return. + + + + + + List of special handlings that applied to this package. (Returned for CSR SL only.) + + + + + (Returned for CSR SL only.) + + + + + Indicates last-known possession of package (Returned for CSR SL only.) + + The address information for the shipper. @@ -801,6 +1405,11 @@ The address of the FedEx pickup location/facility. + + + (Returned for CSR SL only.) + + Estimated package pickup time for shipments that haven't been picked up. @@ -821,16 +1430,54 @@ Total distance package still has to travel. Returned for Custom Critical shipments. + + + Provides additional details about package delivery. + + + + + (Returned for CSR SL only.) + + + + + This is the latest updated destination address. + + The address this package is to be (or has been) delivered. + + + + The address this package is requested to placed on hold. + + + + + (Returned for CSR SL only.) + + The address of the FedEx delivery location/facility. + + + + + Date and time the package should be (or should have been) delivered. (Returned for CSR SL only.) + + + + + Date and time the package would be delivered if the package has appointment delivery as a special service. + + Projected package delivery time based on ship time stamp, service and destination. Not populated if delivery has already occurred. @@ -861,16 +1508,28 @@ User/screen friendly representation of the DeliveryLocationType (delivery location at the delivered to address). Can be returned in localized text. + + + Specifies the number of delivery attempts made to deliver the shipment. + + This is either the name of the person that signed for the package or "Signature not requested" or "Signature on file". - + - True if signed for by signature image is available. + Specifies the details about the count of the packages delivered at the delivery location and the count of the packages at the origin. + + + Specifies the total number of unique addresses on the CRNs in a consolidation. + + + + The types of email notifications that are available for the package. @@ -881,9 +1540,9 @@ Returned for cargo shipments only when they are currently split across vehicles. - + - Indicates redirection eligibility as determined by tracking service, subject to refinement/override by redirect-to-hold service. + Specifies the details about the eligibility for different delivery options. @@ -893,6 +1552,11 @@ + + + + + FedEx scanning information about a package. @@ -928,6 +1592,11 @@ Address information of the station that is responsible for the scan. + + + FedEx location ID where the scan took place. (Returned for CSR SL only.) + + Indicates where the arrival actually occurred. @@ -945,6 +1614,7 @@ + @@ -953,9 +1623,11 @@ + + @@ -1010,123 +1682,11 @@ - - - FedEx Track Notification reply. - - - - - This contains the severity type of the most severe Notification in the Notifications array. - - - - - Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply. - - - - - Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data. - - - - - Contains the version of the reply being used. - - - - - True if duplicate packages (more than one package with the same tracking number) have been found, the packages array contains information about each duplicate. Use this information to determine which of the tracking numbers is the one you need and resend your request using the tracking number and TrackingNumberUniqueIdentifier for that package. - - - - - True if additional packages remain to be retrieved. - - - - - Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true). - - - - - Information about the notifications that are available for this tracking number. If there are duplicates the ship date and destination address information is returned for determining which TrackingNumberUniqueIdentifier to use on a subsequent request. - - - - - - - FedEx Track Notification request. - + - - - Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services). - - - - - Descriptive data identifying the client submitting the transaction. - - - - - Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations - - - - - Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply). - - - - - The tracking number to which the notifications will be triggered from. - - - - - Indicates whether to return tracking information for all associated packages. - - - - - When the MoreDataAvailable field is true in a TrackNotificationReply the PagingToken must be sent in the subsequent TrackNotificationRequest to retrieve the next page of data. - - - - - Use this field when your original request informs you that there are duplicates of this tracking number. If you get duplicates you will also receive some information about each of the duplicate tracking numbers to enable you to chose one and resend that number along with the TrackingNumberUniqueId to get notifications for that tracking number. - - - - - To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates. - - - - - To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates. - - - - - Included in the email notification identifying the requester of this notification. - - - - - Included in the email notification identifying the requester of this notification. - - - - - Who to send the email notifications to and for which events. The notificationRecipientType and NotifyOnShipment fields are not used in this request. - - + + + @@ -1134,18 +1694,41 @@ The type and value of the package identifier that is to be used to retrieve the tracking information for a package. - + - The value to be used to retrieve tracking information for a package. + The type of the Value to be used to retrieve tracking information for a package (e.g. SHIPPER_REFERENCE, PURCHASE_ORDER, TRACKING_NUMBER_OR_DOORTAG, etc..) . - + - The type of the Value to be used to retrieve tracking information for a package (e.g. SHIPPER_REFERENCE, PURCHASE_ORDER, TRACKING_NUMBER_OR_DOORTAG, etc..) . + The value to be used to retrieve tracking information for a package. + + + + + + + + + + + + + + + + + + + + + + + Used to report the status of a piece of a multiple piece shipment which is no longer traveling with the rest of the packages in the shipment or has not been accounted for. @@ -1188,24 +1771,9 @@ Contains the version of the reply being used. - - - True if duplicate packages (more than one package with the same tracking number) have been found, and only limited data will be provided for each one. - - - - - True if additional packages remain to be retrieved. - - - - - Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true). - - - + - Contains detailed tracking information for the requested packages(s). + Contains detailed tracking entity information. @@ -1235,6 +1803,46 @@ The version of the request being used. + + + Specifies the details needed to select the shipment being requested to be tracked. + + + + + The customer can specify a desired time out value for this particular transaction. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The FedEx operating company (transportation) used for this package's delivery. @@ -1245,7 +1853,7 @@ Identifies operating transportation company that is the specific to the carrier code. - + The type and value of the package identifier that is to be used to retrieve the tracking information for a package or group of packages. @@ -1270,29 +1878,181 @@ For tracking by references information either the account number or destination postal code and country must be provided. + + + Specifies the SPOD account number for the shipment being tracked. + + For tracking by references information either the account number or destination postal code and country must be provided. - + - If false the reply will contain summary/profile data including current status. If true the reply contains profile + detailed scan activity for each package. + Specifies the details about how to retrieve the subsequent pages when there is more than one page in the TrackReply. - + - When the MoreData field = true in a TrackReply the PagingToken must be sent in the subsequent TrackRequest to retrieve the next page of data. + The customer can specify a desired time out value for this particular tracking number. - + + + + + + + Specifies a shorter description for the service that is calculated per the service code. + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specifies the status and status update time of the track special instructions. + + + + + Specifies the estimated delivery time that was originally estimated when the shipment was shipped. + + + + + Specifies the time the customer requested a change to the shipment. + + + + + The requested appointment time for delivery. + + + + Used when a cargo shipment is split across vehicles. This is used to give the status of each part of the shipment. @@ -1320,6 +2080,26 @@ + + + + + + + + + + + Specifies the details about the status of the track information for the shipments being tracked. + + + + + + + + + Descriptive data that governs data payload language/translations. The TransactionDetail from the request is echoed back to the caller in the corresponding reply. @@ -1368,6 +2148,11 @@ Used in authentication of the sender's identity. + + + This was renamed from cspCredential. + + Credential used to authenticate a specific software application. This value is provided by FedEx after registration. @@ -1402,7 +2187,7 @@ Identifies a system or sub-system which performs an operation. - + Identifies the service business level. @@ -1421,6 +2206,9 @@ + + + @@ -1433,11 +2221,8 @@ - - - - - + + @@ -1446,10 +2231,6 @@ - - - - @@ -1462,11 +2243,15 @@ + + + + - - + + @@ -1474,8 +2259,8 @@ - - + + @@ -1483,8 +2268,8 @@ - - + + @@ -1492,8 +2277,8 @@ - - + + @@ -1504,7 +2289,7 @@ - + - + \ No newline at end of file diff --git a/app/code/Magento/Fedex/registration.php b/app/code/Magento/Fedex/registration.php index 23e968edcd3f0..4cfeeb8940d67 100644 --- a/app/code/Magento/Fedex/registration.php +++ b/app/code/Magento/Fedex/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Fedex/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Fedex/view/frontend/layout/checkout_index_index.xml index 758217c58b88e..f5ab9ee82e0bd 100644 --- a/app/code/Magento/Fedex/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Fedex/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js index 016a689d5d436..6752f87f5272e 100644 --- a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js +++ b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global define*/ @@ -16,6 +16,9 @@ define( }, 'country_id': { 'required': true + }, + 'city': { + 'required': true } }; } diff --git a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js index 326c3462e25e1..18c88cccbd024 100644 --- a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js +++ b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*global define*/ diff --git a/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js index 74d58b5ee6459..906c23040e747 100644 --- a/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js +++ b/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*browser:true*/ diff --git a/app/code/Magento/GiftMessage/Api/CartRepositoryInterface.php b/app/code/Magento/GiftMessage/Api/CartRepositoryInterface.php index bd6b02b0ce4cd..08c373973ba41 100644 --- a/app/code/Magento/GiftMessage/Api/CartRepositoryInterface.php +++ b/app/code/Magento/GiftMessage/Api/CartRepositoryInterface.php @@ -1,6 +1,6 @@ scopeConfig->getValue( self::XPATH_CONFIG_GIFT_MESSAGE_ALLOW_ITEMS, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store ); - if ($productGiftMessageAllow === '' || is_null($productGiftMessageAllow)) { + if ($productConfig === null || '' === $productConfig || $productConfig == Boolean::VALUE_USE_CONFIG) { return $result; } else { - return $productGiftMessageAllow; + return $productConfig; } } diff --git a/app/code/Magento/GiftMessage/Model/CartRepository.php b/app/code/Magento/GiftMessage/Model/CartRepository.php index e9181f58f833c..d74fe73e645f4 100644 --- a/app/code/Magento/GiftMessage/Model/CartRepository.php +++ b/app/code/Magento/GiftMessage/Model/CartRepository.php @@ -1,7 +1,7 @@ getProduct()->getGiftMessageAvailable(); // use gift message product setting if it is available - if ($isMessageAvailable !== null) { + if ($isMessageAvailable !== null && $isMessageAvailable != Boolean::VALUE_USE_CONFIG) { $itemLevelConfig[$itemId]['is_available'] = (bool)$isMessageAvailable; } $message = $this->itemRepository->get($quote->getId(), $itemId); diff --git a/app/code/Magento/GiftMessage/Model/GiftMessageManager.php b/app/code/Magento/GiftMessage/Model/GiftMessageManager.php index 734f669b615c9..593aaedcb6f6d 100644 --- a/app/code/Magento/GiftMessage/Model/GiftMessageManager.php +++ b/app/code/Magento/GiftMessage/Model/GiftMessageManager.php @@ -1,6 +1,6 @@ checkoutSessionMock = $this->getMock('Magento\Checkout\Model\Session', [], [], '', false); - $this->httpContextMock = $this->getMock('Magento\Framework\App\Http\Context', [], [], '', false); - $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface', [], [], '', false); - $this->localeFormatMock = $this->getMock('Magento\Framework\Locale\FormatInterface', [], [], '', false); - $this->formKeyMock = $this->getMock('Magento\Framework\Data\Form\FormKey', [], [], '', false); - $this->scopeConfigMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false); - $contextMock = $this->getMock('Magento\Framework\App\Helper\Context', [], [], '', false); + $this->checkoutSessionMock = $this->getMock(\Magento\Checkout\Model\Session::class, [], [], '', false); + $this->httpContextMock = $this->getMock(\Magento\Framework\App\Http\Context::class, [], [], '', false); + $this->storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class, [], [], '', false); + $this->localeFormatMock = $this->getMock(\Magento\Framework\Locale\FormatInterface::class, [], [], '', false); + $this->formKeyMock = $this->getMock(\Magento\Framework\Data\Form\FormKey::class, [], [], '', false); + $this->scopeConfigMock = $this->getMock(ScopeConfigInterface::class, [], [], '', false); + $contextMock = $this->getMock(\Magento\Framework\App\Helper\Context::class, [], [], '', false); $this->cartRepositoryMock = $this->getMock( - 'Magento\GiftMessage\Api\CartRepositoryInterface', + \Magento\GiftMessage\Api\CartRepositoryInterface::class, [], [], '', false ); $this->itemRepositoryMock = $this->getMock( - 'Magento\GiftMessage\Api\ItemRepositoryInterface', + \Magento\GiftMessage\Api\ItemRepositoryInterface::class, [], [], '', @@ -108,31 +114,26 @@ public function testGetConfig() $formKey = 'ABCDEFGHIJKLMNOP'; $isFrontUrlSecure = true; $baseUrl = 'https://magento.com/'; - $quoteItemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false); - $productMock = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false); + $quoteItemMock = $this->getMock(\Magento\Quote\Model\Quote\Item::class, [], [], '', false); + $productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); $storeMock = $this->getMock( - 'Magento\Store\Model\Store', + \Magento\Store\Model\Store::class, ['isFrontUrlSecure', 'getBaseUrl', 'getCode'], [], '', false ); $quoteMock = $this->getMock( - 'Magento\Quote\Model\Quote', + \Magento\Quote\Model\Quote::class, ['getQuoteCurrencyCode', 'getStore', 'getIsVirtual', 'getAllVisibleItems', 'getId'], [], '', false ); - $messageMock = $this->getMockForAbstractClass( - 'Magento\GiftMessage\Api\Data\MessageInterface', - [], - '', - false, - false, - false, - ['getData'] - ); + $messageMock = $this->getMockBuilder(\Magento\GiftMessage\Api\Data\MessageInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getData']) + ->getMockForAbstractClass(); $this->scopeConfigMock->expects($this->atLeastOnce())->method('getValue')->willReturnMap( [ @@ -151,7 +152,7 @@ public function testGetConfig() $quoteMock->expects($this->once())->method('getAllVisibleItems')->willReturn([$quoteItemMock]); $quoteItemMock->expects($this->once())->method('getId')->willReturn($itemId); $quoteItemMock->expects($this->any())->method('getProduct')->willReturn($productMock); - $productMock->expects($this->any())->method('getGiftMessageAvailable')->willReturn(false); + $productMock->expects($this->any())->method('getGiftMessageAvailable')->willReturn(Boolean::VALUE_USE_CONFIG); $this->itemRepositoryMock->expects($this->once())->method('get')->with($quoteId, $itemId) ->willReturn($messageMock); $quoteMock->expects($this->once())->method('getQuoteCurrencyCode')->willReturn($currencyCode); @@ -174,7 +175,6 @@ public function testGetConfig() 'orderLevel' => $messageDataMock, 'itemLevel' => [ $itemId => [ - 'is_available' => false, 'message' => $messageDataMock, ], ] diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php index c61d13b296582..5008b9575db5e 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/GiftMessageManagerTest.php @@ -1,7 +1,7 @@ productMock->expects($this->any())->method('getId')->willReturn($productId); + + $configValue = 1; + $this->scopeConfigMock->expects($this->any()) + ->method('getValue') + ->with(GiftMessageHelper::XPATH_CONFIG_GIFT_MESSAGE_ALLOW_ITEMS, ScopeInterface::SCOPE_STORE) + ->willReturn($configValue); + + $data = [$productId => [ + GiftMessage::DATA_SOURCE_DEFAULT => [ + GiftMessage::FIELD_MESSAGE_AVAILABLE => Boolean::VALUE_USE_CONFIG, + ], + ]]; + $expectedResult = [$productId => [ + GiftMessage::DATA_SOURCE_DEFAULT => [ + GiftMessage::FIELD_MESSAGE_AVAILABLE => $configValue, + 'use_config_gift_message_available' => 1 + ], + ]]; + + $this->assertEquals($expectedResult, $this->getModel()->modifyData($data)); + } + + public function testModifyDataUsesConfigurationValuesForNewProduct() + { + $productId = null; + $configValue = 1; + $this->scopeConfigMock->expects($this->any()) + ->method('getValue') + ->with(GiftMessageHelper::XPATH_CONFIG_GIFT_MESSAGE_ALLOW_ITEMS, ScopeInterface::SCOPE_STORE) + ->willReturn($configValue); + + $expectedResult = [$productId => [ + GiftMessage::DATA_SOURCE_DEFAULT => [ + GiftMessage::FIELD_MESSAGE_AVAILABLE => $configValue, + 'use_config_gift_message_available' => 1 + ], + ]]; + + $this->assertEquals($expectedResult, $this->getModel()->modifyData([])); + } } diff --git a/app/code/Magento/GiftMessage/Ui/DataProvider/Product/Modifier/GiftMessage.php b/app/code/Magento/GiftMessage/Ui/DataProvider/Product/Modifier/GiftMessage.php index 606687fe1da1e..6d4fda58848bd 100644 --- a/app/code/Magento/GiftMessage/Ui/DataProvider/Product/Modifier/GiftMessage.php +++ b/app/code/Magento/GiftMessage/Ui/DataProvider/Product/Modifier/GiftMessage.php @@ -1,6 +1,6 @@ locator->getProduct()->getId(); - $value = ''; + $useConfigValue = Boolean::VALUE_USE_CONFIG; - if (isset($data[$modelId][static::DATA_SOURCE_DEFAULT][static::FIELD_MESSAGE_AVAILABLE])) { - $value = $data[$modelId][static::DATA_SOURCE_DEFAULT][static::FIELD_MESSAGE_AVAILABLE]; - } + $isConfigUsed = isset($data[$modelId][static::DATA_SOURCE_DEFAULT][static::FIELD_MESSAGE_AVAILABLE]) + && $data[$modelId][static::DATA_SOURCE_DEFAULT][static::FIELD_MESSAGE_AVAILABLE] == $useConfigValue; - if ('' === $value) { + if ($isConfigUsed || empty($modelId)) { $data[$modelId][static::DATA_SOURCE_DEFAULT][static::FIELD_MESSAGE_AVAILABLE] = $this->getValueFromConfig(); $data[$modelId][static::DATA_SOURCE_DEFAULT]['use_config_' . static::FIELD_MESSAGE_AVAILABLE] = '1'; @@ -129,14 +129,8 @@ protected function customizeAllowGiftMessageField(array $meta) 'data' => [ 'config' => [ 'dataScope' => static::FIELD_MESSAGE_AVAILABLE, - 'imports' => [ - 'disabled' => - '${$.parentName}.use_config_' - . static::FIELD_MESSAGE_AVAILABLE - . ':checked', - ], 'additionalClasses' => 'admin__field-x-small', - 'formElement' => Checkbox::NAME, + 'component' => 'Magento_Ui/js/form/element/single-checkbox-use-config', 'componentType' => Field::NAME, 'prefer' => 'toggle', 'valueMap' => [ @@ -160,6 +154,14 @@ protected function customizeAllowGiftMessageField(array $meta) 'false' => '0', 'true' => '1', ], + 'exports' => [ + 'checked' => '${$.parentName}.' . static::FIELD_MESSAGE_AVAILABLE + . ':isUseConfig', + ], + 'imports' => [ + 'disabled' => '${$.parentName}.' . static::FIELD_MESSAGE_AVAILABLE + . ':isUseDefault', + ] ], ], ], diff --git a/app/code/Magento/GiftMessage/composer.json b/app/code/Magento/GiftMessage/composer.json index aa8c8b5168aa3..446def3f0179b 100644 --- a/app/code/Magento/GiftMessage/composer.json +++ b/app/code/Magento/GiftMessage/composer.json @@ -2,7 +2,7 @@ "name": "magento/module-gift-message", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/module-store": "100.1.*", "magento/module-catalog": "101.0.*", "magento/module-checkout": "100.1.*", @@ -17,7 +17,7 @@ "magento/module-multishipping": "100.1.*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GiftMessage/etc/adminhtml/di.xml b/app/code/Magento/GiftMessage/etc/adminhtml/di.xml index 585c53a711944..ac9582bebc40e 100644 --- a/app/code/Magento/GiftMessage/etc/adminhtml/di.xml +++ b/app/code/Magento/GiftMessage/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/adminhtml/events.xml b/app/code/Magento/GiftMessage/etc/adminhtml/events.xml index 2741ed49dbb19..6ac8eb1411e0b 100644 --- a/app/code/Magento/GiftMessage/etc/adminhtml/events.xml +++ b/app/code/Magento/GiftMessage/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/adminhtml/system.xml b/app/code/Magento/GiftMessage/etc/adminhtml/system.xml index 89228928a651a..b8e28717c426e 100644 --- a/app/code/Magento/GiftMessage/etc/adminhtml/system.xml +++ b/app/code/Magento/GiftMessage/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/catalog_attributes.xml b/app/code/Magento/GiftMessage/etc/catalog_attributes.xml index 6d112591edac6..20596c9b6466a 100644 --- a/app/code/Magento/GiftMessage/etc/catalog_attributes.xml +++ b/app/code/Magento/GiftMessage/etc/catalog_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/config.xml b/app/code/Magento/GiftMessage/etc/config.xml index 9f4e1996f7d93..fd78b91ee0d64 100644 --- a/app/code/Magento/GiftMessage/etc/config.xml +++ b/app/code/Magento/GiftMessage/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/di.xml b/app/code/Magento/GiftMessage/etc/di.xml index d660115822d69..7486b32099b5a 100644 --- a/app/code/Magento/GiftMessage/etc/di.xml +++ b/app/code/Magento/GiftMessage/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/extension_attributes.xml b/app/code/Magento/GiftMessage/etc/extension_attributes.xml index 1bc636cb66464..8ca36ce1507e1 100644 --- a/app/code/Magento/GiftMessage/etc/extension_attributes.xml +++ b/app/code/Magento/GiftMessage/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/fieldset.xml b/app/code/Magento/GiftMessage/etc/fieldset.xml index dfc40cc5c1c58..99c6da99ecf37 100644 --- a/app/code/Magento/GiftMessage/etc/fieldset.xml +++ b/app/code/Magento/GiftMessage/etc/fieldset.xml @@ -1,7 +1,7 @@ @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/GiftMessage/etc/frontend/di.xml b/app/code/Magento/GiftMessage/etc/frontend/di.xml index 19f0f5c95fa67..cb7365b794787 100644 --- a/app/code/Magento/GiftMessage/etc/frontend/di.xml +++ b/app/code/Magento/GiftMessage/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/frontend/events.xml b/app/code/Magento/GiftMessage/etc/frontend/events.xml index 381edb0111978..fd7c77dc499e2 100644 --- a/app/code/Magento/GiftMessage/etc/frontend/events.xml +++ b/app/code/Magento/GiftMessage/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/frontend/routes.xml b/app/code/Magento/GiftMessage/etc/frontend/routes.xml index 5b2f62b0753c9..f1454b3a4265d 100644 --- a/app/code/Magento/GiftMessage/etc/frontend/routes.xml +++ b/app/code/Magento/GiftMessage/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/GiftMessage/etc/module.xml b/app/code/Magento/GiftMessage/etc/module.xml index 33df6bf08e02e..b2deceb6b6d04 100644 --- a/app/code/Magento/GiftMessage/etc/module.xml +++ b/app/code/Magento/GiftMessage/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/webapi.xml b/app/code/Magento/GiftMessage/etc/webapi.xml index a24fbe74c559c..aee7d4443259d 100644 --- a/app/code/Magento/GiftMessage/etc/webapi.xml +++ b/app/code/Magento/GiftMessage/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/etc/webapi_rest/events.xml b/app/code/Magento/GiftMessage/etc/webapi_rest/events.xml index 7afd66acace75..ce2e2ac39d9d4 100644 --- a/app/code/Magento/GiftMessage/etc/webapi_rest/events.xml +++ b/app/code/Magento/GiftMessage/etc/webapi_rest/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/registration.php b/app/code/Magento/GiftMessage/registration.php index a8a77dadb86a8..49add57ba473d 100644 --- a/app/code/Magento/GiftMessage/registration.php +++ b/app/code/Magento/GiftMessage/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_data.xml b/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_data.xml index 307ba157cd14c..b705fa78a060f 100644 --- a/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_data.xml +++ b/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_data.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_items.xml b/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_items.xml index 307ba157cd14c..b705fa78a060f 100644 --- a/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_items.xml +++ b/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_create_load_block_items.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_view.xml b/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_view.xml index be90cf4e30073..dc3de7bf9178f 100644 --- a/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_view.xml +++ b/app/code/Magento/GiftMessage/view/adminhtml/layout/sales_order_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/view/adminhtml/templates/giftoptionsform.phtml b/app/code/Magento/GiftMessage/view/adminhtml/templates/giftoptionsform.phtml index f76e24958f4de..9e8fbf1c5b69d 100644 --- a/app/code/Magento/GiftMessage/view/adminhtml/templates/giftoptionsform.phtml +++ b/app/code/Magento/GiftMessage/view/adminhtml/templates/giftoptionsform.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GiftMessage/view/frontend/layout/checkout_cart_item_renderers.xml b/app/code/Magento/GiftMessage/view/frontend/layout/checkout_cart_item_renderers.xml index fb2d4fd68f68f..ac5e728a828b8 100644 --- a/app/code/Magento/GiftMessage/view/frontend/layout/checkout_cart_item_renderers.xml +++ b/app/code/Magento/GiftMessage/view/frontend/layout/checkout_cart_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GiftMessage/view/frontend/requirejs-config.js b/app/code/Magento/GiftMessage/view/frontend/requirejs-config.js index 208964d20c061..b59db70335d05 100644 --- a/app/code/Magento/GiftMessage/view/frontend/requirejs-config.js +++ b/app/code/Magento/GiftMessage/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -10,4 +10,4 @@ var config = { extraOptions: 'Magento_GiftMessage/extra-options' } } -}; \ No newline at end of file +}; diff --git a/app/code/Magento/GiftMessage/view/frontend/templates/cart/gift_options.phtml b/app/code/Magento/GiftMessage/view/frontend/templates/cart/gift_options.phtml index ed4b5d2f5de0c..230515897d220 100644 --- a/app/code/Magento/GiftMessage/view/frontend/templates/cart/gift_options.phtml +++ b/app/code/Magento/GiftMessage/view/frontend/templates/cart/gift_options.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GiftMessage/view/frontend/templates/cart/item/renderer/actions/gift_options.phtml b/app/code/Magento/GiftMessage/view/frontend/templates/cart/item/renderer/actions/gift_options.phtml index 703c27b82e196..095a97d6630e4 100644 --- a/app/code/Magento/GiftMessage/view/frontend/templates/cart/item/renderer/actions/gift_options.phtml +++ b/app/code/Magento/GiftMessage/view/frontend/templates/cart/item/renderer/actions/gift_options.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-item-level.html b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-item-level.html index 559875c90f75a..a4cde23d6d060 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-item-level.html +++ b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-item-level.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message.html b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message.html index ca929146d5e66..dc7f50107d2f2 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message.html +++ b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GoogleAdwords/Block/Code.php b/app/code/Magento/GoogleAdwords/Block/Code.php index f0fd7222de1c1..84ba572a50302 100644 --- a/app/code/Magento/GoogleAdwords/Block/Code.php +++ b/app/code/Magento/GoogleAdwords/Block/Code.php @@ -2,7 +2,7 @@ /** * Google AdWords Code block * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Block; diff --git a/app/code/Magento/GoogleAdwords/Helper/Data.php b/app/code/Magento/GoogleAdwords/Helper/Data.php index d04c3687627ae..900447e2da3d5 100644 --- a/app/code/Magento/GoogleAdwords/Helper/Data.php +++ b/app/code/Magento/GoogleAdwords/Helper/Data.php @@ -2,7 +2,7 @@ /** * Google AdWords Data Helper * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Helper; diff --git a/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php b/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php index 626f4b99fe7c5..a3b8c31157b61 100644 --- a/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php +++ b/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php @@ -2,7 +2,7 @@ /** * Google AdWords Conversion Abstract Backend model * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Model\Config\Backend; diff --git a/app/code/Magento/GoogleAdwords/Model/Config/Backend/Color.php b/app/code/Magento/GoogleAdwords/Model/Config/Backend/Color.php index 2e7e27daa626a..5a133a098879a 100644 --- a/app/code/Magento/GoogleAdwords/Model/Config/Backend/Color.php +++ b/app/code/Magento/GoogleAdwords/Model/Config/Backend/Color.php @@ -2,7 +2,7 @@ /** * Google AdWords Color Backend model * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Model\Config\Backend; diff --git a/app/code/Magento/GoogleAdwords/Model/Config/Backend/ConversionId.php b/app/code/Magento/GoogleAdwords/Model/Config/Backend/ConversionId.php index bb894f3b69294..3e3d3190999f6 100644 --- a/app/code/Magento/GoogleAdwords/Model/Config/Backend/ConversionId.php +++ b/app/code/Magento/GoogleAdwords/Model/Config/Backend/ConversionId.php @@ -2,7 +2,7 @@ /** * Google AdWords Conversion Id Backend model * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Model\Config\Backend; diff --git a/app/code/Magento/GoogleAdwords/Model/Config/Source/Language.php b/app/code/Magento/GoogleAdwords/Model/Config/Source/Language.php index 4d5c399cdbac8..01e2bebeeff3a 100644 --- a/app/code/Magento/GoogleAdwords/Model/Config/Source/Language.php +++ b/app/code/Magento/GoogleAdwords/Model/Config/Source/Language.php @@ -2,7 +2,7 @@ /** * Google AdWords language source * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Model\Config\Source; diff --git a/app/code/Magento/GoogleAdwords/Model/Config/Source/ValueType.php b/app/code/Magento/GoogleAdwords/Model/Config/Source/ValueType.php index bc11e17b6a56b..35dd325af3a64 100644 --- a/app/code/Magento/GoogleAdwords/Model/Config/Source/ValueType.php +++ b/app/code/Magento/GoogleAdwords/Model/Config/Source/ValueType.php @@ -2,7 +2,7 @@ /** * Google AdWords conversation value type source * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Model\Config\Source; diff --git a/app/code/Magento/GoogleAdwords/Model/Filter/UppercaseTitle.php b/app/code/Magento/GoogleAdwords/Model/Filter/UppercaseTitle.php index bd35e76d59bd7..d984abd2de550 100644 --- a/app/code/Magento/GoogleAdwords/Model/Filter/UppercaseTitle.php +++ b/app/code/Magento/GoogleAdwords/Model/Filter/UppercaseTitle.php @@ -2,7 +2,7 @@ /** * Filter to uppercase the first character of each word in a string * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Model\Filter; diff --git a/app/code/Magento/GoogleAdwords/Model/Validator/Factory.php b/app/code/Magento/GoogleAdwords/Model/Validator/Factory.php index bcade6bde44c7..6f9e08e202c71 100644 --- a/app/code/Magento/GoogleAdwords/Model/Validator/Factory.php +++ b/app/code/Magento/GoogleAdwords/Model/Validator/Factory.php @@ -2,7 +2,7 @@ /** * Google AdWords Validator Factory * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. * @SuppressWarnings(PHPMD.LongVariable) */ diff --git a/app/code/Magento/GoogleAdwords/Observer/SetConversionValueObserver.php b/app/code/Magento/GoogleAdwords/Observer/SetConversionValueObserver.php index 5f1578f7ee672..2c62a670c342a 100644 --- a/app/code/Magento/GoogleAdwords/Observer/SetConversionValueObserver.php +++ b/app/code/Magento/GoogleAdwords/Observer/SetConversionValueObserver.php @@ -2,7 +2,7 @@ /** * Google AdWords module observer * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GoogleAdwords\Observer; diff --git a/app/code/Magento/GoogleAdwords/Test/Unit/Helper/DataTest.php b/app/code/Magento/GoogleAdwords/Test/Unit/Helper/DataTest.php index 7919b05b0fa94..77f24e19ef0e8 100644 --- a/app/code/Magento/GoogleAdwords/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/GoogleAdwords/Test/Unit/Helper/DataTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GoogleAdwords/etc/config.xml b/app/code/Magento/GoogleAdwords/etc/config.xml index a27ef2ae59661..33278c81226c8 100644 --- a/app/code/Magento/GoogleAdwords/etc/config.xml +++ b/app/code/Magento/GoogleAdwords/etc/config.xml @@ -1,7 +1,7 @@ @@ -69,4 +69,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/GoogleAdwords/etc/di.xml b/app/code/Magento/GoogleAdwords/etc/di.xml index ab368af295294..8e6bfa9f58324 100644 --- a/app/code/Magento/GoogleAdwords/etc/di.xml +++ b/app/code/Magento/GoogleAdwords/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleAdwords/etc/frontend/events.xml b/app/code/Magento/GoogleAdwords/etc/frontend/events.xml index 08e4497f4b477..ee30ac6cc0998 100644 --- a/app/code/Magento/GoogleAdwords/etc/frontend/events.xml +++ b/app/code/Magento/GoogleAdwords/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleAdwords/etc/module.xml b/app/code/Magento/GoogleAdwords/etc/module.xml index 1e34c30b93790..c0549848ea442 100644 --- a/app/code/Magento/GoogleAdwords/etc/module.xml +++ b/app/code/Magento/GoogleAdwords/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleAdwords/registration.php b/app/code/Magento/GoogleAdwords/registration.php index 9d1ca0a3dae78..816ca597014aa 100644 --- a/app/code/Magento/GoogleAdwords/registration.php +++ b/app/code/Magento/GoogleAdwords/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GoogleAdwords/view/frontend/templates/code.phtml b/app/code/Magento/GoogleAdwords/view/frontend/templates/code.phtml index dae452b9373e9..27717a2fade96 100644 --- a/app/code/Magento/GoogleAdwords/view/frontend/templates/code.phtml +++ b/app/code/Magento/GoogleAdwords/view/frontend/templates/code.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GoogleAnalytics/etc/adminhtml/system.xml b/app/code/Magento/GoogleAnalytics/etc/adminhtml/system.xml index a5a5df5d68556..1238ab525e1a4 100644 --- a/app/code/Magento/GoogleAnalytics/etc/adminhtml/system.xml +++ b/app/code/Magento/GoogleAnalytics/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleAnalytics/etc/di.xml b/app/code/Magento/GoogleAnalytics/etc/di.xml index c837007469acc..9865bf935e489 100644 --- a/app/code/Magento/GoogleAnalytics/etc/di.xml +++ b/app/code/Magento/GoogleAnalytics/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleAnalytics/etc/frontend/events.xml b/app/code/Magento/GoogleAnalytics/etc/frontend/events.xml index a325d25a9722d..bf2d3695ef11a 100644 --- a/app/code/Magento/GoogleAnalytics/etc/frontend/events.xml +++ b/app/code/Magento/GoogleAnalytics/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleAnalytics/etc/module.xml b/app/code/Magento/GoogleAnalytics/etc/module.xml index ff0205f27a33c..2f19cf9e03294 100644 --- a/app/code/Magento/GoogleAnalytics/etc/module.xml +++ b/app/code/Magento/GoogleAnalytics/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleAnalytics/registration.php b/app/code/Magento/GoogleAnalytics/registration.php index 8781279105f19..778faafb34ef3 100644 --- a/app/code/Magento/GoogleAnalytics/registration.php +++ b/app/code/Magento/GoogleAnalytics/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GoogleAnalytics/view/frontend/templates/ga.phtml b/app/code/Magento/GoogleAnalytics/view/frontend/templates/ga.phtml index 0093f91e6cdab..52a7f186a19bd 100644 --- a/app/code/Magento/GoogleAnalytics/view/frontend/templates/ga.phtml +++ b/app/code/Magento/GoogleAnalytics/view/frontend/templates/ga.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GoogleOptimizer/etc/adminhtml/system.xml b/app/code/Magento/GoogleOptimizer/etc/adminhtml/system.xml index 50b5ad1f81c04..ff58c7a6467a2 100644 --- a/app/code/Magento/GoogleOptimizer/etc/adminhtml/system.xml +++ b/app/code/Magento/GoogleOptimizer/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/etc/config.xml b/app/code/Magento/GoogleOptimizer/etc/config.xml index 9704a13537f89..fd0cf59f56861 100644 --- a/app/code/Magento/GoogleOptimizer/etc/config.xml +++ b/app/code/Magento/GoogleOptimizer/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/etc/events.xml b/app/code/Magento/GoogleOptimizer/etc/events.xml index 41a8917513c12..d637f28fe47d1 100644 --- a/app/code/Magento/GoogleOptimizer/etc/events.xml +++ b/app/code/Magento/GoogleOptimizer/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/etc/module.xml b/app/code/Magento/GoogleOptimizer/etc/module.xml index 692a5960f89a5..1c5f5c124a912 100644 --- a/app/code/Magento/GoogleOptimizer/etc/module.xml +++ b/app/code/Magento/GoogleOptimizer/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/registration.php b/app/code/Magento/GoogleOptimizer/registration.php index 52517d100db4a..1d648a2983e2a 100644 --- a/app/code/Magento/GoogleOptimizer/registration.php +++ b/app/code/Magento/GoogleOptimizer/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GoogleOptimizer/view/adminhtml/layout/cms_page_edit.xml b/app/code/Magento/GoogleOptimizer/view/adminhtml/layout/cms_page_edit.xml index 3b337f5a333c7..d2c8863956d3e 100644 --- a/app/code/Magento/GoogleOptimizer/view/adminhtml/layout/cms_page_edit.xml +++ b/app/code/Magento/GoogleOptimizer/view/adminhtml/layout/cms_page_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/category_form.xml b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/category_form.xml index 3fc937e6f1c6b..1387e4a2e6783 100644 --- a/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/category_form.xml +++ b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/category_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/cms_page_form.xml b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/cms_page_form.xml index c27ea723a0570..235b216d8fb67 100644 --- a/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/cms_page_form.xml +++ b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/cms_page_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/new_category_form.xml b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/new_category_form.xml index 632dc91b45b8c..264dabcc861ca 100644 --- a/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/new_category_form.xml +++ b/app/code/Magento/GoogleOptimizer/view/adminhtml/ui_component/new_category_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_category_view.xml b/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_category_view.xml index 3725ba5fc5e4d..f2d1a03d1fd7c 100644 --- a/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_category_view.xml +++ b/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_category_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_product_view.xml index 89ac360a8cee8..50a5e534cb536 100644 --- a/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/GoogleOptimizer/view/frontend/layout/catalog_product_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GoogleOptimizer/view/frontend/layout/cms_page_view.xml b/app/code/Magento/GoogleOptimizer/view/frontend/layout/cms_page_view.xml index 3890610f9c3eb..f2c032e7bed02 100644 --- a/app/code/Magento/GoogleOptimizer/view/frontend/layout/cms_page_view.xml +++ b/app/code/Magento/GoogleOptimizer/view/frontend/layout/cms_page_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedImportExport/Model/Export/Product/Type/Grouped.php b/app/code/Magento/GroupedImportExport/Model/Export/Product/Type/Grouped.php index ad153c297b329..3e7b4a3976938 100644 --- a/app/code/Magento/GroupedImportExport/Model/Export/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedImportExport/Model/Export/Product/Type/Grouped.php @@ -2,7 +2,7 @@ /** * Export entity of grouped product type * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\GroupedImportExport\Model\Export\Product\Type; diff --git a/app/code/Magento/GroupedImportExport/Model/Export/RowCustomizer.php b/app/code/Magento/GroupedImportExport/Model/Export/RowCustomizer.php index 62cd9c6aa996f..dff2663dea913 100644 --- a/app/code/Magento/GroupedImportExport/Model/Export/RowCustomizer.php +++ b/app/code/Magento/GroupedImportExport/Model/Export/RowCustomizer.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GroupedImportExport/etc/export.xml b/app/code/Magento/GroupedImportExport/etc/export.xml index a41343cbfae53..5271ad58bbbd5 100644 --- a/app/code/Magento/GroupedImportExport/etc/export.xml +++ b/app/code/Magento/GroupedImportExport/etc/export.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedImportExport/etc/import.xml b/app/code/Magento/GroupedImportExport/etc/import.xml index 9e25ef3addccd..d82507f622b9b 100644 --- a/app/code/Magento/GroupedImportExport/etc/import.xml +++ b/app/code/Magento/GroupedImportExport/etc/import.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedImportExport/etc/module.xml b/app/code/Magento/GroupedImportExport/etc/module.xml index 60a23f6122a87..1051080c6c0bb 100644 --- a/app/code/Magento/GroupedImportExport/etc/module.xml +++ b/app/code/Magento/GroupedImportExport/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedImportExport/registration.php b/app/code/Magento/GroupedImportExport/registration.php index 284dc9b4eff00..1f5d2158a51ae 100644 --- a/app/code/Magento/GroupedImportExport/registration.php +++ b/app/code/Magento/GroupedImportExport/registration.php @@ -1,6 +1,6 @@ + */ +interface GroupedInterface +{ + /** + * Reindex for all products + * + * @return $this + */ + public function reindexAll(); + + /** + * Reindex for defined product(s) + * + * @param int|array $entityIds + * @return $this + */ + public function reindexEntity($entityIds); +} diff --git a/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link.php b/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link.php index 5af791c45085a..e86bc9f182e09 100644 --- a/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link.php +++ b/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link.php @@ -1,6 +1,6 @@ getMock(); $this->saleableItem->expects($this->once()) diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Pricing/Price/FinalPriceTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Pricing/Price/FinalPriceTest.php index 3382d18a39355..392da0d2ac4dc 100644 --- a/app/code/Magento/GroupedProduct/Test/Unit/Pricing/Price/FinalPriceTest.php +++ b/app/code/Magento/GroupedProduct/Test/Unit/Pricing/Price/FinalPriceTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GroupedProduct/etc/adminhtml/routes.xml b/app/code/Magento/GroupedProduct/etc/adminhtml/routes.xml index 970710dedebd8..b56a47161b0cb 100644 --- a/app/code/Magento/GroupedProduct/etc/adminhtml/routes.xml +++ b/app/code/Magento/GroupedProduct/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/etc/adminhtml/system.xml b/app/code/Magento/GroupedProduct/etc/adminhtml/system.xml index b8a6c6b51de28..c295f7abf44ce 100644 --- a/app/code/Magento/GroupedProduct/etc/adminhtml/system.xml +++ b/app/code/Magento/GroupedProduct/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/etc/config.xml b/app/code/Magento/GroupedProduct/etc/config.xml index 539c3d72b05b4..6f33654ca8ac7 100644 --- a/app/code/Magento/GroupedProduct/etc/config.xml +++ b/app/code/Magento/GroupedProduct/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/etc/di.xml b/app/code/Magento/GroupedProduct/etc/di.xml index 459198a2bb338..788052d07fca5 100644 --- a/app/code/Magento/GroupedProduct/etc/di.xml +++ b/app/code/Magento/GroupedProduct/etc/di.xml @@ -1,7 +1,7 @@ @@ -87,4 +87,6 @@ + diff --git a/app/code/Magento/GroupedProduct/etc/extension_attributes.xml b/app/code/Magento/GroupedProduct/etc/extension_attributes.xml index 89a5cdeb1c7f3..dec84c4c27a98 100644 --- a/app/code/Magento/GroupedProduct/etc/extension_attributes.xml +++ b/app/code/Magento/GroupedProduct/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/etc/frontend/di.xml b/app/code/Magento/GroupedProduct/etc/frontend/di.xml index ce50f40144c9f..a6ad9efbb0eb3 100644 --- a/app/code/Magento/GroupedProduct/etc/frontend/di.xml +++ b/app/code/Magento/GroupedProduct/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/etc/module.xml b/app/code/Magento/GroupedProduct/etc/module.xml index 5a03ee430ea1b..2294ea45aab55 100644 --- a/app/code/Magento/GroupedProduct/etc/module.xml +++ b/app/code/Magento/GroupedProduct/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/etc/pdf.xml b/app/code/Magento/GroupedProduct/etc/pdf.xml index ea1c03dacac44..24f0ff29518c5 100644 --- a/app/code/Magento/GroupedProduct/etc/pdf.xml +++ b/app/code/Magento/GroupedProduct/etc/pdf.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/etc/product_types.xml b/app/code/Magento/GroupedProduct/etc/product_types.xml index 6ba69db4838a4..3b4f7b7fbeb79 100644 --- a/app/code/Magento/GroupedProduct/etc/product_types.xml +++ b/app/code/Magento/GroupedProduct/etc/product_types.xml @@ -1,14 +1,14 @@ - + diff --git a/app/code/Magento/GroupedProduct/etc/sales.xml b/app/code/Magento/GroupedProduct/etc/sales.xml index 914ec168ec32b..16b18b4415d9f 100644 --- a/app/code/Magento/GroupedProduct/etc/sales.xml +++ b/app/code/Magento/GroupedProduct/etc/sales.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/registration.php b/app/code/Magento/GroupedProduct/registration.php index ae4763b0f375c..c0e1e34bc2824 100644 --- a/app/code/Magento/GroupedProduct/registration.php +++ b/app/code/Magento/GroupedProduct/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_new.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_new.xml index 2dd2171001988..6647ba4365458 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_new.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_view_type_grouped.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_view_type_grouped.xml index a67f1c6f6201b..d8bcde7f55d30 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_view_type_grouped.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/catalog_product_view_type_grouped.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_edit_popup.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_edit_popup.xml index 9875355a70546..6e8587a805a33 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_edit_popup.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_edit_popup.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml index 8fb09eaa0f9cf..ab3c4204c4ab4 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_new.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_new.xml index 0135aa7521236..dc9a19e91ed76 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_new.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml index 0135aa7521236..dc9a19e91ed76 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_updateqty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_view.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_view.xml index 1f370af9fd503..9ed2f6976c78e 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_view.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_creditmemo_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_new.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_new.xml index 0135aa7521236..dc9a19e91ed76 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_new.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_new.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_updateqty.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_updateqty.xml index 0135aa7521236..dc9a19e91ed76 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_updateqty.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_updateqty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_view.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_view.xml index 31f256e8a27ed..d40b0405bcf82 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_view.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_invoice_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_view.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_view.xml index 0135aa7521236..dc9a19e91ed76 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_view.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/sales_order_view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/requirejs-config.js b/app/code/Magento/GroupedProduct/view/adminhtml/requirejs-config.js index b223755c35edf..7fdb1fe9c9250 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/GroupedProduct/view/adminhtml/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,4 +9,4 @@ var config = { groupedProduct: 'Magento_GroupedProduct/js/grouped-product' } } -}; \ No newline at end of file +}; 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 26eee1d66eef6..96c918e8ff8e6 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 @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/ui_component/grouped_product_listing.xml b/app/code/Magento/GroupedProduct/view/adminhtml/ui_component/grouped_product_listing.xml index 9d356d53ce613..b29cc9c97d38d 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/ui_component/grouped_product_listing.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/ui_component/grouped_product_listing.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ grouped_product_listing.grouped_product_listing_data_source product_columns + Magento_Catalog::products diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/web/css/grouped-product.css b/app/code/Magento/GroupedProduct/view/adminhtml/web/css/grouped-product.css index 769b1d81821f5..df86b3bc44be1 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/web/css/grouped-product.css +++ b/app/code/Magento/GroupedProduct/view/adminhtml/web/css/grouped-product.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js b/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js index ba1a46bf17d38..d8841f2118f15 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js +++ b/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true */ diff --git a/app/code/Magento/GroupedProduct/view/base/layout/catalog_product_prices.xml b/app/code/Magento/GroupedProduct/view/base/layout/catalog_product_prices.xml index 0b391109dcf37..d13e6611a935c 100644 --- a/app/code/Magento/GroupedProduct/view/base/layout/catalog_product_prices.xml +++ b/app/code/Magento/GroupedProduct/view/base/layout/catalog_product_prices.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml b/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml index bcdbcbcc424d3..bce8f36f12f7d 100644 --- a/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml +++ b/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml index 6c8f871a3632d..ef17f6f2ebaa4 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_cart_item_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_cart_item_renderers.xml index 2101c940c3a4d..2d6dc79b7643e 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_cart_item_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_cart_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml index 216f8736d2915..b713558b10633 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/checkout_onepage_review_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 1de085ae24198..13952d3bc7c00 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_invoice_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_invoice_renderers.xml index 3ee63835c4c4d..ca6e286e30f69 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_invoice_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_renderers.xml index 11f93d5e7c1fa..9f2166f345e0b 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_guest_invoice.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_guest_invoice.xml index fd3e59f7e2a9f..495268bb8e5d9 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_guest_invoice.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_guest_invoice.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_creditmemo_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_creditmemo_renderers.xml index 2732a60331875..30eebc159fdb3 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_creditmemo_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_invoice_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_invoice_renderers.xml index fd3e59f7e2a9f..495268bb8e5d9 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_invoice_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_item_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_item_renderers.xml index 28873219cefbb..c51e36c80b86a 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_item_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_item_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_creditmemo_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_creditmemo_renderers.xml index 941430f3773db..e0a9fca4a41a9 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_creditmemo_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_creditmemo_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_invoice_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_invoice_renderers.xml index f1da901e54a9f..fb76469b4eaaf 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_invoice_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_invoice_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_renderers.xml index c01e8e7e0f688..bbf433f80e406 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_order_print_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/default.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/default.phtml index a5b5de2bf2c77..054fcb95038e0 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/default.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/default.phtml @@ -1,6 +1,6 @@ $this->_formatFactory->create()->toOptionArray() ] ); + $fieldset->addField( + \Magento\ImportExport\Model\Export::FIELDS_ENCLOSURE, + 'checkbox', + [ + 'name' => \Magento\ImportExport\Model\Export::FIELDS_ENCLOSURE, + 'label' => __('Fields Enclosure'), + 'title' => __('Fields Enclosure'), + 'value' => 1, + ] + ); $form->setUseContainer(true); $this->setForm($form); diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php b/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php index 0c10ca794a613..89efd649f69c5 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php @@ -1,6 +1,6 @@ Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, ] ); + $fieldsets[$behaviorCode]->addField( + $behaviorCode . \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE, + 'checkbox', + [ + 'name' => \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE, + 'label' => __('Fields enclosure'), + 'title' => __('Fields enclosure'), + 'value' => 1, + ] + ); } // fieldset for file uploading diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Frame/Result.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Frame/Result.php index 4cbb8a918d3f5..7c7fbaa01d94e 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Frame/Result.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Frame/Result.php @@ -1,6 +1,6 @@ indexerRegistry->get($indexerId); - $indexer->invalidate(); + if (!$indexer->isScheduled()) { + $indexer->invalidate(); + } } catch (\InvalidArgumentException $e) { } } diff --git a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php index 6333b1e63ea69..e5adfb3c8764f 100644 --- a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_merged_valid.xml b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_merged_valid.xml index 244b0b91e9fda..b1cf370e1c5dd 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_merged_valid.xml +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_merged_valid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_valid.xml b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_valid.xml index 13490296206e8..c59fb52f05704 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_valid.xml +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/export_valid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportMergedXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportMergedXmlArray.php index b3a801d85b860..66121ce773b75 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportMergedXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Export/Config/_files/invalidExportMergedXmlArray.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php index f63163d5f5f6b..35c8a8e854712 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/invalidImportMergedXmlArray.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/valid_import_merged.xml b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/valid_import_merged.xml index 20596d3b814ed..f6ea8ddaa7025 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/valid_import_merged.xml +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Config/_files/valid_import_merged.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php index d57d3ac869a0f..1d872223453c6 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ImportExport/etc/adminhtml/menu.xml b/app/code/Magento/ImportExport/etc/adminhtml/menu.xml index ea9c15ad7a673..32f33227952b3 100644 --- a/app/code/Magento/ImportExport/etc/adminhtml/menu.xml +++ b/app/code/Magento/ImportExport/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/adminhtml/routes.xml b/app/code/Magento/ImportExport/etc/adminhtml/routes.xml index 459629f7b3640..22448a8609aa0 100644 --- a/app/code/Magento/ImportExport/etc/adminhtml/routes.xml +++ b/app/code/Magento/ImportExport/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/config.xml b/app/code/Magento/ImportExport/etc/config.xml index 8614565f5fd98..7a7fe0e10e9b6 100644 --- a/app/code/Magento/ImportExport/etc/config.xml +++ b/app/code/Magento/ImportExport/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/di.xml b/app/code/Magento/ImportExport/etc/di.xml index de637c7104dac..4c357782d80c3 100644 --- a/app/code/Magento/ImportExport/etc/di.xml +++ b/app/code/Magento/ImportExport/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/export.xsd b/app/code/Magento/ImportExport/etc/export.xsd index c7316873d8998..e6d69809d55b9 100644 --- a/app/code/Magento/ImportExport/etc/export.xsd +++ b/app/code/Magento/ImportExport/etc/export.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/export_merged.xsd b/app/code/Magento/ImportExport/etc/export_merged.xsd index 200a173b81f07..352c78ee76038 100644 --- a/app/code/Magento/ImportExport/etc/export_merged.xsd +++ b/app/code/Magento/ImportExport/etc/export_merged.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/import.xsd b/app/code/Magento/ImportExport/etc/import.xsd index 2d6ab40c3c895..4aac9792ce741 100644 --- a/app/code/Magento/ImportExport/etc/import.xsd +++ b/app/code/Magento/ImportExport/etc/import.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/import_merged.xsd b/app/code/Magento/ImportExport/etc/import_merged.xsd index c654c04c8ded4..898a835c7b2d7 100644 --- a/app/code/Magento/ImportExport/etc/import_merged.xsd +++ b/app/code/Magento/ImportExport/etc/import_merged.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/etc/module.xml b/app/code/Magento/ImportExport/etc/module.xml index fde05d4e2448d..0b7b0329c39c3 100644 --- a/app/code/Magento/ImportExport/etc/module.xml +++ b/app/code/Magento/ImportExport/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/registration.php b/app/code/Magento/ImportExport/registration.php index 80dce0d7e03b3..e879d8fe8217c 100644 --- a/app/code/Magento/ImportExport/registration.php +++ b/app/code/Magento/ImportExport/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_export_index.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_export_index.xml index 53783e0a31026..f81887fe53896 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_export_index.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_export_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml index 3ff79ba46ccc5..3e8e26d45635e 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_grid_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_index.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_index.xml index 1055151c3d739..70ec84dd18638 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_index.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_history_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_busy.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_busy.xml index ed04365a172c9..96923815d4001 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_busy.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_busy.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_index.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_index.xml index 1e99b42c3182a..e6485407fce68 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_index.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_start.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_start.xml index cac0aa44a22ee..0c03442c8ad20 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_start.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_start.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_validate.xml b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_validate.xml index cac0aa44a22ee..0c03442c8ad20 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_validate.xml +++ b/app/code/Magento/ImportExport/view/adminhtml/layout/adminhtml_import_validate.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/busy.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/busy.phtml index cd77de6c78d86..ad186e1c78a6f 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/busy.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/busy.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml index e551dca72e224..2b036ffb11360 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml @@ -1,6 +1,6 @@ @@ -80,6 +80,9 @@ require([ var oldAction = form.action; var url = oldAction + ((oldAction.slice(-1) != '/') ? '/' : '') + 'entity/' + $F('entity') + '/file_format/' + $F('file_format'); + if ($F('fields_enclosure')) { + url += '/fields_enclosure/' + $F('fields_enclosure'); + } form.action = url; form.submit(); form.action = oldAction; diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/filter/after.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/filter/after.phtml index aa2dbce2b72a5..365ad1a22587a 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/filter/after.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/filter/after.phtml @@ -1,6 +1,6 @@ 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 62ac37926260e..513d32073b97c 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 @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/ImportExport/view/adminhtml/web/css/importexport.css b/app/code/Magento/ImportExport/view/adminhtml/web/css/importexport.css index 9ddae017cbcea..6d08f0be2b94a 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/web/css/importexport.css +++ b/app/code/Magento/ImportExport/view/adminhtml/web/css/importexport.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ .import-error-wrapper { diff --git a/app/code/Magento/Indexer/App/Indexer.php b/app/code/Magento/Indexer/App/Indexer.php index 58c58608984a3..827d7393bed37 100644 --- a/app/code/Magento/Indexer/App/Indexer.php +++ b/app/code/Magento/Indexer/App/Indexer.php @@ -1,6 +1,6 @@ eventManager->dispatch('clean_cache_after_reindex', ['object' => $this->context]); + if (!empty($this->context->getIdentities())) { + $this->getCache()->clean($this->context->getIdentities()); + } } /** @@ -51,5 +61,22 @@ public function afterUpdateMview(\Magento\Indexer\Model\Processor $subject) public function afterReindexAllInvalid(\Magento\Indexer\Model\Processor $subject) { $this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->context]); + if (!empty($this->context->getIdentities())) { + $this->getCache()->clean($this->context->getIdentities()); + } + } + + /** + * Get cache interface + * + * @return \Magento\Framework\App\CacheInterface + * @deprecated + */ + private function getCache() + { + if ($this->cache === null) { + $this->cache = \Magento\Framework\App\ObjectManager::getInstance()->get(CacheInterface::class); + } + return $this->cache; } } diff --git a/app/code/Magento/Indexer/Model/Processor/Handler.php b/app/code/Magento/Indexer/Model/Processor/Handler.php index b280a44e7b566..c03ebab2d5c61 100644 --- a/app/code/Magento/Indexer/Model/Processor/Handler.php +++ b/app/code/Magento/Indexer/Model/Processor/Handler.php @@ -1,6 +1,6 @@ subjectMock = $this->getMock('Magento\Indexer\Model\Processor', [], [], '', false); - $this->contextMock = $this->getMock('Magento\Framework\Indexer\CacheContext', [], [], '', false); - $this->eventManagerMock = $this->getMock('Magento\Framework\Event\Manager', [], [], '', false); - $this->plugin = new \Magento\Indexer\Model\Processor\CleanCache( + $this->objectManager = new ObjectManager($this); + $this->subjectMock = $this->getMock(\Magento\Indexer\Model\Processor::class, [], [], '', false); + $this->contextMock = $this->getMock(\Magento\Framework\Indexer\CacheContext::class, [], [], '', false); + $this->eventManagerMock = $this->getMock(\Magento\Framework\Event\Manager::class, [], [], '', false); + $this->cacheMock = $this->getMock(\Magento\Framework\App\CacheInterface::class, [], [], '', false); + $this->plugin = new CleanCache( $this->contextMock, $this->eventManagerMock ); + + $reflection = new \ReflectionClass(get_class($this->plugin)); + $reflectionProperty = $reflection->getProperty('cache'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->plugin, $this->cacheMock); } /** @@ -56,12 +78,22 @@ protected function setUp() */ public function testAfterUpdateMview() { + $tags = ['tag_name1', 'tag_name2']; $this->eventManagerMock->expects($this->once()) ->method('dispatch') ->with( $this->equalTo('clean_cache_after_reindex'), $this->equalTo(['object' => $this->contextMock]) ); + + $this->contextMock->expects($this->atLeastOnce()) + ->method('getIdentities') + ->willReturn($tags); + + $this->cacheMock->expects($this->once()) + ->method('clean') + ->with($tags); + $this->plugin->afterUpdateMview($this->subjectMock); } } diff --git a/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php b/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php index d992f41ce720d..9c5fe8f5d4cba 100644 --- a/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php +++ b/app/code/Magento/Indexer/Test/Unit/Model/ProcessorTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Indexer/etc/adminhtml/di.xml b/app/code/Magento/Indexer/etc/adminhtml/di.xml index 5f6a5d7200dba..76b8f8b841120 100644 --- a/app/code/Magento/Indexer/etc/adminhtml/di.xml +++ b/app/code/Magento/Indexer/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Indexer/etc/adminhtml/menu.xml b/app/code/Magento/Indexer/etc/adminhtml/menu.xml index 09fc0b2e5ffbf..432a0cf1a9d0e 100644 --- a/app/code/Magento/Indexer/etc/adminhtml/menu.xml +++ b/app/code/Magento/Indexer/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Indexer/etc/adminhtml/routes.xml b/app/code/Magento/Indexer/etc/adminhtml/routes.xml index 0e134cd64a08a..ceccb8d0917c6 100644 --- a/app/code/Magento/Indexer/etc/adminhtml/routes.xml +++ b/app/code/Magento/Indexer/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Indexer/etc/cron_groups.xml b/app/code/Magento/Indexer/etc/cron_groups.xml index d3d7ccd1994d9..8d5309c9657a1 100644 --- a/app/code/Magento/Indexer/etc/cron_groups.xml +++ b/app/code/Magento/Indexer/etc/cron_groups.xml @@ -1,7 +1,7 @@ @@ -15,4 +15,4 @@ 600 1
- \ No newline at end of file + diff --git a/app/code/Magento/Indexer/etc/crontab.xml b/app/code/Magento/Indexer/etc/crontab.xml index 7bf3d2ed610aa..b3a701c1dd651 100644 --- a/app/code/Magento/Indexer/etc/crontab.xml +++ b/app/code/Magento/Indexer/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Indexer/etc/di.xml b/app/code/Magento/Indexer/etc/di.xml index 80b42bd2f72e4..1d3f125406f7d 100644 --- a/app/code/Magento/Indexer/etc/di.xml +++ b/app/code/Magento/Indexer/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Indexer/etc/module.xml b/app/code/Magento/Indexer/etc/module.xml index 01e57c942a37b..a2beac159902b 100644 --- a/app/code/Magento/Indexer/etc/module.xml +++ b/app/code/Magento/Indexer/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Indexer/registration.php b/app/code/Magento/Indexer/registration.php index e589abd999953..ac23ea0b4e6b3 100644 --- a/app/code/Magento/Indexer/registration.php +++ b/app/code/Magento/Indexer/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml b/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml index 6def568e9cbbd..87a88add07d18 100644 --- a/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml +++ b/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Integration/Api/AdminTokenServiceInterface.php b/app/code/Magento/Integration/Api/AdminTokenServiceInterface.php index f7b12e6afb734..e7368e74f4e92 100644 --- a/app/code/Magento/Integration/Api/AdminTokenServiceInterface.php +++ b/app/code/Magento/Integration/Api/AdminTokenServiceInterface.php @@ -1,6 +1,6 @@ tag with "edit" action for the integration grid. * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Integration\Block\Adminhtml\Widget\Grid\Column\Renderer\Button; diff --git a/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Button/Edit.php b/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Button/Edit.php index 1e87b194ac648..81ed706a5785a 100644 --- a/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Button/Edit.php +++ b/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Button/Edit.php @@ -2,7 +2,7 @@ /** * Render HTML

'; + $html .= sprintf( + 'Configuration Details', + $element->getComment() + ); + $html .= '

'; + $expected .= 'Configuration Details'; + $expected .= '

getStatusLabel() ?>
getRealOrderId() ?> formatDate($_order->getCreatedAt()) ?> getShippingAddress() ? $block->escapeHtml($_order->getShippingAddress()->getName()) : ' ' ?> formatPrice($_order->getGrandTotal()) ?> getStatusLabel() ?>
+ + + + + + + + getCarrierTitle()): ?> + + + + + + getErrorMessage()): ?> + + + + + getTrackSummary()): ?> + + + + + getUrl()): ?> + + + + + + $property): ?> + $property())): ?> + + + + + + + + getDeliverydate()): ?> + + + + + + + + + + + + + + +
escapeHtml(__('Order tracking')); ?>
escapeHtml(__('Tracking Number:')); ?>escapeHtml($track->getTracking()); ?>
escapeHtml(__('Carrier:')); ?>escapeHtml($track->getCarrierTitle()); ?>
escapeHtml(__('Error:')); ?> + escapeHtml(__('Tracking information is currently not available. Please ')); ?> + getContactUsEnabled()) : ?> + + escapeHtml(__('contact us')); ?> + + escapeHtml(__(' for more information or ')); ?> + + escapeHtml(__('email us at ')); ?> + +
escapeHtml(__('Info:')); ?>escapeHtml($track->getTrackSummary()); ?>
escapeHtml(__('Track:')); ?> + + escapeUrl($track->getUrl()); ?> + +
escapeHtml(__($title . ':')); ?>escapeHtml($track->$property()); ?>
escapeHtml(__('Delivered on:')); ?> + formatDeliveryDateTime($track->getDeliverydate(), $track->getDeliverytime()); ?> +
+ escapeHtml($track['title']) : $block->escapeHtml(__('N/A'))); ?>: + escapeHtml($track['number']) : ''); ?>
diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/link.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/link.phtml index c858b29f6bc9f..a4c6eac90db3a 100644 --- a/app/code/Magento/Shipping/view/frontend/templates/tracking/link.phtml +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/link.phtml @@ -1,6 +1,6 @@ getTrackingInfo(); ?> - -getTrackingInfo(); ?>
- 0): ?> - $_result): ?> - -
- - 0): ?> - - -
- - - - - - - - - getCarrierTitle()): ?> - - - - - - getErrorMessage()): ?> - - - - - getTrackSummary()): ?> - - - - - getUrl()): ?> - - - - - - getStatus()): ?> - - - - - - - getDeliverydate()): ?> - - - - - - - getSignedby()): ?> - - - - - - - getDeliveryLocation()): ?> - - - - - - - getShippedDate()): ?> - - - - - - - getService()): ?> - - - - - - - getWeight()): ?> - - - - - - - - - - - - - - -
escapeHtml($track->getTracking()); ?>
escapeHtml($track->getCarrierTitle()); ?>
getContactUsEnabled()) : ?>getStoreSupportEmail() ?>
getTrackSummary(); ?>
escapeHtml($track->getUrl()); ?>
getStatus(); ?>
formatDeliveryDateTime($track->getDeliverydate(), $track->getDeliverytime()); ?>
getSignedby(); ?>
getDeliveryLocation(); ?>
getShippedDate(); ?>
getService(); ?>
getWeight(); ?>
escapeHtml($track['title']) : __('N/A')); ?>:escapeHtml($track['number']) : ''); ?>
-
- getProgressdetail())>0): ?> + + $result): ?> + +
escapeHtml(__('Shipment #')) . $shipId; ?>
+ + + $track): ?>
- - - - - - - - - - - - getProgressdetail() as $_detail): ?> - formatDeliveryDate($_detail['deliverydate']) : '') ?> - formatDeliveryTime($_detail['deliverytime'], $_detail['deliverydate']) : '') ?> - - - - - - - - -
+ addChild('shipping.tracking.details.' . $counter, Template::class, [ + 'track' => $track, + 'template' => 'Magento_Shipping::tracking/details.phtml', + 'storeSupportEmail' => $block->getStoreSupportEmail() + ] + ); + ?> + getChildHtml('shipping.tracking.details.' . $counter); ?>
- - - - - - - -
- - - + getProgressdetail())): ?> + addChild('shipping.tracking.progress.'. $counter, Template::class, [ + 'track' => $track, + 'template' => 'Magento_Shipping::tracking/progress.phtml' + ]); + ?> + getChildHtml('shipping.tracking.progress.' . $counter); ?> + + + +
+
escapeHtml(__('There is no tracking available for this shipment.')); ?>
+
+ + -
+
+
escapeHtml(__('There is no tracking available.')); ?>
+
diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/progress.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/progress.phtml new file mode 100644 index 0000000000000..9022a5815824b --- /dev/null +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/progress.phtml @@ -0,0 +1,43 @@ +getData('track'); +?> +
+ + + + + + + + + + + + getProgressdetail() as $detail): ?> + formatDeliveryDate($detail['deliverydate']) : ''); ?> + formatDeliveryTime($detail['deliverytime'], $detail['deliverydate']) : ''); ?> + + + + + + + + +
escapeHtml(__('Track history')); ?>
escapeHtml(__('Location')); ?>escapeHtml(__('Date')); ?>escapeHtml(__('Local Time')); ?>escapeHtml(__('Description')); ?>
+ escapeHtml($detail['deliverylocation']) : ''); ?> + + + + + escapeHtml($detail['activity']) : ''); ?> +
+
diff --git a/app/code/Magento/Shipping/view/frontend/web/js/model/config.js b/app/code/Magento/Shipping/view/frontend/web/js/model/config.js index 0deb24ed2d054..1250517318e8d 100644 --- a/app/code/Magento/Shipping/view/frontend/web/js/model/config.js +++ b/app/code/Magento/Shipping/view/frontend/web/js/model/config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ diff --git a/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js b/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js index 5626bb085b535..408cdbde9762b 100644 --- a/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js +++ b/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html b/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html index 790fa15e8bf8f..80ca54bf876a7 100644 --- a/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html +++ b/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sitemap/Block/Adminhtml/Edit.php b/app/code/Magento/Sitemap/Block/Adminhtml/Edit.php index 66596db9f561d..d5ae6bd57d841 100644 --- a/app/code/Magento/Sitemap/Block/Adminhtml/Edit.php +++ b/app/code/Magento/Sitemap/Block/Adminhtml/Edit.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-2.xml b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-2.xml index 09007b2e6d954..e785e457848bd 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-2.xml +++ b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-2.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-3.xml b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-3.xml index 53046393af40d..e3b3d2daf2bb7 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-3.xml +++ b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-3.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-4.xml b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-4.xml index b8efca330cbf6..6726a7116f686 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-4.xml +++ b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-1-4.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-index.xml b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-index.xml index c0166c9e7a831..5d79195f885ce 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-index.xml +++ b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-single.xml b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-single.xml index 8291553ae9a9a..bff7c169f22a2 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-single.xml +++ b/app/code/Magento/Sitemap/Test/Unit/Model/_files/sitemap-single.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/composer.json b/app/code/Magento/Sitemap/composer.json index 943de59ee1ea8..ef44b292ae2b1 100644 --- a/app/code/Magento/Sitemap/composer.json +++ b/app/code/Magento/Sitemap/composer.json @@ -2,7 +2,7 @@ "name": "magento/module-sitemap", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/module-store": "100.1.*", "magento/module-catalog": "101.0.*", "magento/module-eav": "100.1.*", @@ -13,7 +13,7 @@ "magento/framework": "100.1.*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sitemap/etc/acl.xml b/app/code/Magento/Sitemap/etc/acl.xml index 397f1ba351351..d73e94c20b111 100644 --- a/app/code/Magento/Sitemap/etc/acl.xml +++ b/app/code/Magento/Sitemap/etc/acl.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/etc/adminhtml/menu.xml b/app/code/Magento/Sitemap/etc/adminhtml/menu.xml index 6a20c6c679d8f..09fc00e072cd0 100644 --- a/app/code/Magento/Sitemap/etc/adminhtml/menu.xml +++ b/app/code/Magento/Sitemap/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/etc/adminhtml/routes.xml b/app/code/Magento/Sitemap/etc/adminhtml/routes.xml index c26d736986136..69e5b2f4daa7f 100644 --- a/app/code/Magento/Sitemap/etc/adminhtml/routes.xml +++ b/app/code/Magento/Sitemap/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/etc/adminhtml/system.xml b/app/code/Magento/Sitemap/etc/adminhtml/system.xml index d29550bec28f6..ad837ed929460 100644 --- a/app/code/Magento/Sitemap/etc/adminhtml/system.xml +++ b/app/code/Magento/Sitemap/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/etc/config.xml b/app/code/Magento/Sitemap/etc/config.xml index 274cd54fb8158..bc722938f29d4 100644 --- a/app/code/Magento/Sitemap/etc/config.xml +++ b/app/code/Magento/Sitemap/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/etc/crontab.xml b/app/code/Magento/Sitemap/etc/crontab.xml index e62402c2b1f83..0155d4628b550 100644 --- a/app/code/Magento/Sitemap/etc/crontab.xml +++ b/app/code/Magento/Sitemap/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/etc/di.xml b/app/code/Magento/Sitemap/etc/di.xml index 7ce1fdee7b5b6..538d76d925e77 100644 --- a/app/code/Magento/Sitemap/etc/di.xml +++ b/app/code/Magento/Sitemap/etc/di.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,11 @@ Magento\Sitemap\Model\ResourceModel\Sitemap + + + + 1 + + + diff --git a/app/code/Magento/Sitemap/etc/email_templates.xml b/app/code/Magento/Sitemap/etc/email_templates.xml index a8aa9fa8912a5..ac31a5d1333a5 100644 --- a/app/code/Magento/Sitemap/etc/email_templates.xml +++ b/app/code/Magento/Sitemap/etc/email_templates.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/etc/module.xml b/app/code/Magento/Sitemap/etc/module.xml index b57c37a27db7d..13cab4dbd80b5 100644 --- a/app/code/Magento/Sitemap/etc/module.xml +++ b/app/code/Magento/Sitemap/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/registration.php b/app/code/Magento/Sitemap/registration.php index 273bd908fcaea..206e520ce7441 100644 --- a/app/code/Magento/Sitemap/registration.php +++ b/app/code/Magento/Sitemap/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index.xml b/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index.xml index c45045e4cf25a..93373638ca780 100644 --- a/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index.xml +++ b/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml b/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml index 1c70a3b8e3a85..dc5d1f60706f5 100644 --- a/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml +++ b/app/code/Magento/Sitemap/view/adminhtml/layout/adminhtml_sitemap_index_grid_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/Api/Data/GroupInterface.php b/app/code/Magento/Store/Api/Data/GroupInterface.php index cb051a1a8cd94..5bd91c28d43e6 100644 --- a/app/code/Magento/Store/Api/Data/GroupInterface.php +++ b/app/code/Magento/Store/Api/Data/GroupInterface.php @@ -1,6 +1,6 @@ websiteCollectionFactory = $websiteCollectionFactory; + $this->groupCollectionFactory = $groupCollectionFactory; + $this->storeCollectionFactory = $storeCollectionFactory; + $this->deploymentConfig = $deploymentConfig; + $this->websiteFactory = $websiteFactory; + $this->groupFactory = $groupFactory; + $this->storeFactory = $storeFactory; + } + + /** + * @inheritdoc + */ + public function get($path = '') + { + if (strpos($path, '/') === false) { + $scopePool = $path; + $scopeCode = null; + } else { + list($scopePool, $scopeCode) = explode('/', $path); + } + + $data = []; + if ($this->canUseDatabase()) { + switch ($scopePool) { + case 'websites': + $data['websites'] = $this->getWebsitesData($scopeCode); + break; + case 'groups': + $data['groups'] = $this->getGroupsData($scopeCode); + break; + case 'stores': + $data['stores'] = $this->getStoresData($scopeCode); + break; + default: + $data = [ + 'websites' => $this->getWebsitesData(), + 'groups' => $this->getGroupsData(), + 'stores' => $this->getStoresData(), + ]; + break; + } + } + + return $data; + } + + /** + * @param string|null $code + * @return array + */ + private function getWebsitesData($code = null) + { + if ($code !== null) { + $website = $this->websiteFactory->create(); + $website->load($code); + $data[$code] = $website->getData(); + } else { + $collection = $this->websiteCollectionFactory->create(); + $collection->setLoadDefault(true); + $data = []; + /** @var Website $website */ + foreach ($collection as $website) { + $data[$website->getCode()] = $website->getData(); + } + } + return $data; + } + + /** + * @param string|null $id + * @return array + */ + private function getGroupsData($id = null) + { + if ($id !== null) { + $group = $this->groupFactory->create(); + $group->load($id); + $data[$id] = $group->getData(); + } else { + $collection = $this->groupCollectionFactory->create(); + $collection->setLoadDefault(true); + $data = []; + /** @var Group $group */ + foreach ($collection as $group) { + $data[$group->getId()] = $group->getData(); + } + } + return $data; + } + + /** + * @param string|null $code + * @return array + */ + private function getStoresData($code = null) + { + if ($code !== null) { + $store = $this->storeFactory->create(); + + if (is_numeric($code)) { + $store->load($code); + } else { + $store->load($code, 'code'); + } + + $data[$code] = $store->getData(); + } else { + $collection = $this->storeCollectionFactory->create(); + $collection->setLoadDefault(true); + $data = []; + /** @var Store $store */ + foreach ($collection as $store) { + $data[$store->getCode()] = $store->getData(); + } + return $data; + } + return $data; + } + + /** + * Check whether db connection is available and can be used + * + * @return bool + */ + private function canUseDatabase() + { + return $this->deploymentConfig->get('db'); + } +} diff --git a/app/code/Magento/Store/App/Config/Type/Scopes.php b/app/code/Magento/Store/App/Config/Type/Scopes.php new file mode 100644 index 0000000000000..88b3961da4096 --- /dev/null +++ b/app/code/Magento/Store/App/Config/Type/Scopes.php @@ -0,0 +1,65 @@ +source = $source; + $this->data = new DataObject(); + } + + /** + * @inheritdoc + */ + public function get($path = '') + { + $patchChunks = explode("/", $path); + + if (!$this->data->getData($path) || count($patchChunks) == 1) { + $this->data->addData($this->source->get($path)); + } + + return $this->data->getData($path); + } + + /** + * Clean cache + * + * @return void + */ + public function clean() + { + $this->data = new DataObject(); + } +} diff --git a/app/code/Magento/Store/App/FrontController/Plugin/DefaultStore.php b/app/code/Magento/Store/App/FrontController/Plugin/DefaultStore.php index ac2400ca4742e..ca10e73f88b01 100644 --- a/app/code/Magento/Store/App/FrontController/Plugin/DefaultStore.php +++ b/app/code/Magento/Store/App/FrontController/Plugin/DefaultStore.php @@ -1,6 +1,6 @@ _processor = $processor; - } - /** * Convert config data * @@ -31,7 +21,6 @@ public function __construct(\Magento\Store\Model\Config\Processor\Placeholder $p */ public function convert($source, $initialConfig = []) { - $config = array_replace_recursive($initialConfig, parent::convert($source)); - return $this->_processor->process($config); + return array_replace_recursive($initialConfig, parent::convert($source)); } } diff --git a/app/code/Magento/Store/Model/Config/Placeholder.php b/app/code/Magento/Store/Model/Config/Placeholder.php new file mode 100644 index 0000000000000..88aacc7be41e5 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Placeholder.php @@ -0,0 +1,165 @@ +request = $request; + $this->urlPaths = $urlPaths; + $this->urlPlaceholder = $urlPlaceholder; + } + + /** + * Replace placeholders with config values + * + * @param array $data + * @return array + */ + public function process(array $data = []) + { + foreach (array_keys($data) as $key) { + $this->_processData($data, $key); + } + return $data; + } + + /** + * Process array data recursively + * + * @param array &$data + * @param string $path + * @return void + */ + protected function _processData(&$data, $path) + { + $configValue = $this->_getValue($path, $data); + if (is_array($configValue)) { + foreach (array_keys($configValue) as $key) { + $this->_processData($data, $path . '/' . $key); + } + } else { + $this->_setValue($data, $path, $this->_processPlaceholders($configValue, $data)); + } + } + + /** + * Replace placeholders with config values + * + * @param string $value + * @param array $data + * @return string + */ + protected function _processPlaceholders($value, $data) + { + $placeholder = $this->_getPlaceholder($value); + if ($placeholder) { + $url = false; + if ($placeholder == 'unsecure_base_url') { + $url = $this->_getValue($this->urlPaths['unsecureBaseUrl'], $data); + } elseif ($placeholder == 'secure_base_url') { + $url = $this->_getValue($this->urlPaths['secureBaseUrl'], $data); + } + + if ($url) { + $value = str_replace('{{' . $placeholder . '}}', $url, $value); + } elseif (strpos($value, $this->urlPlaceholder) !== false) { + $distroBaseUrl = $this->request->getDistroBaseUrl(); + $value = str_replace($this->urlPlaceholder, $distroBaseUrl, $value); + } + + if (null !== $this->_getPlaceholder($value)) { + $value = $this->_processPlaceholders($value, $data); + } + } + return $value; + } + + /** + * Get placeholder from value + * + * @param string $value + * @return string|null + */ + protected function _getPlaceholder($value) + { + if (is_string($value) && preg_match('/{{(.*)}}.*/', $value, $matches)) { + $placeholder = $matches[1]; + if ($placeholder == 'unsecure_base_url' || $placeholder == 'secure_base_url' || strpos( + $value, + $this->urlPlaceholder + ) !== false + ) { + return $placeholder; + } + } + return null; + } + + /** + * Get array value by path + * + * @param string $path + * @param array $data + * @return array|null + */ + protected function _getValue($path, array $data) + { + $keys = explode('/', $path); + foreach ($keys as $key) { + if (is_array($data) && (isset($data[$key]) || array_key_exists($key, $data))) { + $data = $data[$key]; + } else { + return null; + } + } + return $data; + } + + /** + * Set array value by path + * + * @param array &$container + * @param string $path + * @param string $value + * @return void + */ + protected function _setValue(array &$container, $path, $value) + { + $segments = explode('/', $path); + $currentPointer = & $container; + foreach ($segments as $segment) { + if (!isset($currentPointer[$segment])) { + $currentPointer[$segment] = []; + } + $currentPointer = & $currentPointer[$segment]; + } + $currentPointer = $value; + } +} diff --git a/app/code/Magento/Store/Model/Config/Processor/Fallback.php b/app/code/Magento/Store/Model/Config/Processor/Fallback.php new file mode 100644 index 0000000000000..655eb3ad03943 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Processor/Fallback.php @@ -0,0 +1,182 @@ +scopes = $scopes; + $this->resourceConnection = $resourceConnection; + $this->storeResource = $storeResource; + $this->websiteResource = $websiteResource; + $this->deploymentConfig = $deploymentConfig; + } + + /** + * @inheritdoc + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function process(array $data) + { + if ($this->deploymentConfig->isDbAvailable()) {//read only from db + $this->storeData = $this->storeResource->readAllStores(); + $this->websiteData = $this->websiteResource->readAllWebsites(); + } else { + $this->storeData = $this->scopes->get('stores'); + $this->websiteData = $this->scopes->get('websites'); + } + + $defaultConfig = isset($data['default']) ? $data['default'] : []; + $result = [ + 'default' => $defaultConfig, + 'websites' => [], + 'stores' => [] + ]; + + $websitesConfig = isset($data['websites']) ? $data['websites'] : []; + $result['websites'] = $this->prepareWebsitesConfig($defaultConfig, $websitesConfig); + + $storesConfig = isset($data['stores']) ? $data['stores'] : []; + $result['stores'] = $this->prepareStoresConfig($defaultConfig, $websitesConfig, $storesConfig); + + return $result; + } + + /** + * Prepare website data from Config/Type/Scopes + * + * @param array $defaultConfig + * @param array $websitesConfig + * @return array + */ + private function prepareWebsitesConfig( + array $defaultConfig, + array $websitesConfig + ) { + $result = []; + foreach ($this->websiteData as $website) { + $code = $website['code']; + $id = $website['website_id']; + $websiteConfig = isset($websitesConfig[$code]) ? $websitesConfig[$code] : []; + $result[$code] = array_replace_recursive($defaultConfig, $websiteConfig); + $result[$id] = $result[$code]; + } + return $result; + } + + /** + * Prepare stores data from Config/Type/Scopes + * + * @param array $defaultConfig + * @param array $websitesConfig + * @param array $storesConfig + * @return array + */ + private function prepareStoresConfig( + array $defaultConfig, + array $websitesConfig, + array $storesConfig + ) { + $result = []; + + foreach ($this->storeData as $store) { + $code = $store['code']; + $id = $store['store_id']; + $websiteConfig = []; + if (isset($store['website_id'])) { + $websiteConfig = $this->getWebsiteConfig($websitesConfig, $store['website_id']); + } + $storeConfig = isset($storesConfig[$code]) ? $storesConfig[$code] : []; + $result[$code] = array_replace_recursive($defaultConfig, $websiteConfig, $storeConfig); + $result[$id] = $result[$code]; + } + return $result; + } + + /** + * Find by id specific information about website. + * + * @param array $websites Has next format: (website_code => [website_data]) + * @param int $id + * @return array + */ + private function getWebsiteConfig(array $websites, $id) + { + foreach ($this->websiteData as $website) { + if ($website['website_id'] == $id) { + $code = $website['code']; + return isset($websites[$code]) ? $websites[$code] : []; + } + } + + return []; + } +} diff --git a/app/code/Magento/Store/Model/Config/Processor/Placeholder.php b/app/code/Magento/Store/Model/Config/Processor/Placeholder.php index ac15026705388..19a03d1d08934 100644 --- a/app/code/Magento/Store/Model/Config/Processor/Placeholder.php +++ b/app/code/Magento/Store/Model/Config/Processor/Placeholder.php @@ -2,164 +2,81 @@ /** * Placeholder configuration values processor. Replace placeholders in configuration with config values * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Store\Model\Config\Processor; -class Placeholder +use Magento\Framework\App\Config\Spi\PostProcessorInterface; +use Magento\Store\Model\Config\Placeholder as ConfigPlaceholder; +use Magento\Framework\App\ObjectManager; + +/** + * Placeholder configuration values processor. Replace placeholders in configuration with config values + * @package Magento\Store\Model\Config\Processor + */ +class Placeholder implements PostProcessorInterface { /** * @var \Magento\Framework\App\RequestInterface + * + * @deprecated */ protected $request; /** * @var string[] + * + * @deprecated */ protected $urlPaths; /** * @var string + * + * @deprecated */ protected $urlPlaceholder; /** + * @var ConfigPlaceholder + */ + private $configPlaceholder; + + /** + * Placeholder constructor. * @param \Magento\Framework\App\RequestInterface $request * @param string[] $urlPaths - * @param string $urlPlaceholder + * @param string|null $urlPlaceholder + * @param ConfigPlaceholder|null $configPlaceholder */ - public function __construct(\Magento\Framework\App\RequestInterface $request, $urlPaths, $urlPlaceholder) - { + public function __construct( + \Magento\Framework\App\RequestInterface $request, + $urlPaths = [], + $urlPlaceholder = null, + ConfigPlaceholder $configPlaceholder = null + ) { $this->request = $request; $this->urlPaths = $urlPaths; $this->urlPlaceholder = $urlPlaceholder; + $this->configPlaceholder = $configPlaceholder ?: ObjectManager::getInstance()->get(ConfigPlaceholder::class); } /** - * Replace placeholders with config values - * - * @param array $data - * @return array + * @inheritdoc */ - public function process(array $data = []) + public function process(array $data) { - foreach (array_keys($data) as $key) { - $this->_processData($data, $key); - } - return $data; - } - - /** - * Process array data recursively - * - * @param array &$data - * @param string $path - * @return void - */ - protected function _processData(&$data, $path) - { - $configValue = $this->_getValue($path, $data); - if (is_array($configValue)) { - foreach (array_keys($configValue) as $key) { - $this->_processData($data, $path . '/' . $key); - } - } else { - $this->_setValue($data, $path, $this->_processPlaceholders($configValue, $data)); - } - } - - /** - * Replace placeholders with config values - * - * @param string $value - * @param array $data - * @return string - */ - protected function _processPlaceholders($value, $data) - { - $placeholder = $this->_getPlaceholder($value); - if ($placeholder) { - $url = false; - if ($placeholder == 'unsecure_base_url') { - $url = $this->_getValue($this->urlPaths['unsecureBaseUrl'], $data); - } elseif ($placeholder == 'secure_base_url') { - $url = $this->_getValue($this->urlPaths['secureBaseUrl'], $data); - } - - if ($url) { - $value = str_replace('{{' . $placeholder . '}}', $url, $value); - } elseif (strpos($value, $this->urlPlaceholder) !== false) { - $distroBaseUrl = $this->request->getDistroBaseUrl(); - $value = str_replace($this->urlPlaceholder, $distroBaseUrl, $value); - } - - if (null !== $this->_getPlaceholder($value)) { - $value = $this->_processPlaceholders($value, $data); - } - } - return $value; - } - - /** - * Get placeholder from value - * - * @param string $value - * @return string|null - */ - protected function _getPlaceholder($value) - { - if (is_string($value) && preg_match('/{{(.*)}}.*/', $value, $matches)) { - $placeholder = $matches[1]; - if ($placeholder == 'unsecure_base_url' || $placeholder == 'secure_base_url' || strpos( - $value, - $this->urlPlaceholder - ) !== false - ) { - return $placeholder; - } - } - return null; - } - - /** - * Get array value by path - * - * @param string $path - * @param array $data - * @return array|null - */ - protected function _getValue($path, array $data) - { - $keys = explode('/', $path); - foreach ($keys as $key) { - if (is_array($data) && (isset($data[$key]) || array_key_exists($key, $data))) { - $data = $data[$key]; + foreach ($data as $scope => &$scopeData) { + if ($scope === 'default') { + $scopeData = $this->configPlaceholder->process($scopeData); } else { - return null; + foreach ($scopeData as &$sData) { + $sData = $this->configPlaceholder->process($sData); + } } } - return $data; - } - /** - * Set array value by path - * - * @param array &$container - * @param string $path - * @param string $value - * @return void - */ - protected function _setValue(array &$container, $path, $value) - { - $segments = explode('/', $path); - $currentPointer = & $container; - foreach ($segments as $segment) { - if (!isset($currentPointer[$segment])) { - $currentPointer[$segment] = []; - } - $currentPointer = & $currentPointer[$segment]; - } - $currentPointer = $value; + return $data; } } diff --git a/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php b/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php deleted file mode 100644 index 6436f1895a675..0000000000000 --- a/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php +++ /dev/null @@ -1,73 +0,0 @@ -_initialConfig = $initialConfig; - $this->_converter = $converter; - $this->_collectionFactory = $collectionFactory; - } - - /** - * Read configuration data - * - * @param null|string $scope - * @throws LocalizedException Exception is thrown when scope other than default is given - * @return array - */ - public function read($scope = null) - { - $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' => $scope] - ); - $dbDefaultConfig = []; - foreach ($collection as $item) { - $dbDefaultConfig[$item->getPath()] = $item->getValue(); - } - $dbDefaultConfig = $this->_converter->convert($dbDefaultConfig); - $config = array_replace_recursive($config, $dbDefaultConfig); - - return $config; - } -} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/DefaultScope.php b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/DefaultScope.php new file mode 100644 index 0000000000000..6251a1bf0841d --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/DefaultScope.php @@ -0,0 +1,61 @@ +collectionFactory = $collectionFactory; + $this->converter = $converter; + } + + /** + * Retrieve config by default scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + $collection = $this->collectionFactory->create( + ['scope' => ScopeConfigInterface::SCOPE_TYPE_DEFAULT] + ); + } catch (\DomainException $e) { + $collection = []; + } + $config = []; + foreach ($collection as $item) { + $config[$item->getPath()] = $item->getValue(); + } + return $this->converter->convert($config); + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Store.php b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Store.php new file mode 100644 index 0000000000000..41d5b3b470697 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Store.php @@ -0,0 +1,92 @@ +collectionFactory = $collectionFactory; + $this->converter = $converter; + $this->websiteFactory = $websiteFactory; + $this->websiteSource = $websiteSource; + $this->storeManager = $storeManager; + } + + /** + * Retrieve config by store scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + $store = $this->storeManager->getStore($scopeCode); + $collection = $this->collectionFactory->create( + ['scope' => ScopeInterface::SCOPE_STORES, 'scopeId' => $store->getId()] + ); + + $config = []; + foreach ($collection as $item) { + $config[$item->getPath()] = $item->getValue(); + } + return $this->converter->convert(array_replace_recursive( + $this->websiteSource->get($store->getWebsiteId()), + $this->converter->convert($config) + )); + } catch (\DomainException $e) { + return []; + } + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Website.php b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Website.php new file mode 100644 index 0000000000000..f5ccaa1210360 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Website.php @@ -0,0 +1,80 @@ +collectionFactory = $collectionFactory; + $this->converter = $converter; + $this->websiteFactory = $websiteFactory; + $this->defaultScope = $defaultScope; + } + + /** + * Retrieve config by website scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + $website = $this->websiteFactory->create(); + $website->load($scopeCode); + $collection = $this->collectionFactory->create( + ['scope' => ScopeInterface::SCOPE_WEBSITES, 'scopeId' => $website->getId()] + ); + $config = []; + foreach ($collection as $item) { + $config[$item->getPath()] = $item->getValue(); + } + return array_replace_recursive($this->defaultScope->get(), $this->converter->convert($config)); + } catch (\DomainException $e) { + return []; + } + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Initial/DefaultScope.php b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/DefaultScope.php new file mode 100644 index 0000000000000..ee227fee1be93 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/DefaultScope.php @@ -0,0 +1,50 @@ +initialConfig = $initialConfig; + $this->converter = $converter; + } + + /** + * Retrieve config by default scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + return $this->converter->convert($this->initialConfig->getData(ScopeConfigInterface::SCOPE_TYPE_DEFAULT)); + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Store.php b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Store.php new file mode 100644 index 0000000000000..650ca37737d0c --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Store.php @@ -0,0 +1,75 @@ +initialConfig = $initialConfig; + $this->websiteSource = $website; + $this->storeManager = $storeManager; + $this->converter = $converter; + } + + /** + * Retrieve config by store scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + /** @var \Magento\Store\Model\Store $store */ + $store = $this->storeManager->getStore($scopeCode); + return $this->converter->convert(array_replace_recursive( + $this->websiteSource->get($store->getData('website_code')), + $this->initialConfig->getData("stores|{$scopeCode}") + )); + } catch (\Exception $e) { + return []; + } + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Website.php b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Website.php new file mode 100644 index 0000000000000..f6225d6853468 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Website.php @@ -0,0 +1,60 @@ +initialConfig = $initialConfig; + $this->defaultScope = $defaultScope; + $this->converter = $converter; + } + + /** + * Retrieve config by website scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + return $this->converter->convert(array_replace_recursive( + $this->defaultScope->get(), + $this->initialConfig->getData("websites|{$scopeCode}") + )); + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Store.php b/app/code/Magento/Store/Model/Config/Reader/Store.php deleted file mode 100644 index 8b4eb2d673651..0000000000000 --- a/app/code/Magento/Store/Model/Config/Reader/Store.php +++ /dev/null @@ -1,84 +0,0 @@ -_initialConfig = $initialConfig; - $this->_scopePool = $scopePool; - $this->_converter = $converter; - $this->_collectionFactory = $collectionFactory; - $this->_storeManager = $storeManager; - } - - /** - * Read configuration by code - * - * @param null|string $code - * @return array - * @throws NoSuchEntityException - */ - public function read($code = null) - { - $store = $this->_storeManager->getStore($code); - - $websiteConfig = $this->_scopePool->getScope( - \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE, - $store->getWebsite()->getCode() - )->getSource(); - $config = array_replace_recursive($websiteConfig, $this->_initialConfig->getData("stores|{$code}")); - - $collection = $this->_collectionFactory->create( - ['scope' => \Magento\Store\Model\ScopeInterface::SCOPE_STORES, 'scopeId' => $store->getId()] - ); - $dbStoreConfig = []; - foreach ($collection as $item) { - $dbStoreConfig[$item->getPath()] = $item->getValue(); - } - return $this->_converter->convert($dbStoreConfig, $config); - } -} diff --git a/app/code/Magento/Store/Model/Config/Reader/Website.php b/app/code/Magento/Store/Model/Config/Reader/Website.php deleted file mode 100644 index 3ae30ea86a506..0000000000000 --- a/app/code/Magento/Store/Model/Config/Reader/Website.php +++ /dev/null @@ -1,88 +0,0 @@ -_initialConfig = $initialConfig; - $this->_scopePool = $scopePool; - $this->_converter = $converter; - $this->_collectionFactory = $collectionFactory; - $this->_websiteFactory = $websiteFactory; - } - - /** - * Read configuration by code - * - * @param string $code - * @return array - */ - public function read($code = null) - { - $config = array_replace_recursive( - $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT)->getSource(), - $this->_initialConfig->getData("websites|{$code}") - ); - - $website = $this->_websiteFactory->create(); - $website->load($code); - $collection = $this->_collectionFactory->create( - ['scope' => \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, 'scopeId' => $website->getId()] - ); - $dbWebsiteConfig = []; - foreach ($collection as $configValue) { - $dbWebsiteConfig[$configValue->getPath()] = $configValue->getValue(); - } - $dbWebsiteConfig = $this->_converter->convert($dbWebsiteConfig); - - if (count($dbWebsiteConfig)) { - $config = array_replace_recursive($config, $dbWebsiteConfig); - } - - return $config; - } -} diff --git a/app/code/Magento/Store/Model/Config/StoreView.php b/app/code/Magento/Store/Model/Config/StoreView.php index f26c32979872e..4e8085a75f9a1 100644 --- a/app/code/Magento/Store/Model/Config/StoreView.php +++ b/app/code/Magento/Store/Model/Config/StoreView.php @@ -1,6 +1,6 @@ getId()]; + return [self::CACHE_TAG]; } /** diff --git a/app/code/Magento/Store/Model/GroupRepository.php b/app/code/Magento/Store/Model/GroupRepository.php index 3cc833138b241..79d97aad815fc 100644 --- a/app/code/Magento/Store/Model/GroupRepository.php +++ b/app/code/Magento/Store/Model/GroupRepository.php @@ -1,12 +1,19 @@ entities[$id])) { return $this->entities[$id]; } - $group = $this->groupFactory->create(); - $group->load($id); + + $group = $this->groupFactory->create([ + 'data' => $this->getAppConfig()->get('scopes', "groups/$id", []) + ]); + if (null === $group->getId()) { throw new NoSuchEntityException(); } @@ -64,14 +79,16 @@ public function get($id) public function getList() { if (!$this->allLoaded) { - /** @var \Magento\Store\Model\ResourceModel\Group\Collection $groupCollection */ - $groupCollection = $this->groupCollectionFactory->create(); - $groupCollection->setLoadDefault(true); - foreach ($groupCollection as $item) { - $this->entities[$item->getId()] = $item; + $groups = $this->getAppConfig()->get('scopes', 'groups', []); + foreach ($groups as $data) { + $group = $this->groupFactory->create([ + 'data' => $data + ]); + $this->entities[$group->getId()] = $group; } $this->allLoaded = true; } + return $this->entities; } @@ -83,4 +100,18 @@ public function clean() $this->entities = []; $this->allLoaded = false; } + + /** + * Retrieve application config. + * + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if (!$this->appConfig) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } } diff --git a/app/code/Magento/Store/Model/HeaderProvider/Hsts.php b/app/code/Magento/Store/Model/HeaderProvider/Hsts.php index bdaf88cb396e7..0f17c021e0258 100644 --- a/app/code/Magento/Store/Model/HeaderProvider/Hsts.php +++ b/app/code/Magento/Store/Model/HeaderProvider/Hsts.php @@ -1,6 +1,6 @@ getConnection() + ->select() + ->from($this->getTable('store')); + + return $this->getConnection()->fetchAll($select); + } + /** * Retrieve select object for load object data * diff --git a/app/code/Magento/Store/Model/ResourceModel/Store/Collection.php b/app/code/Magento/Store/Model/ResourceModel/Store/Collection.php index a8786c61284d9..78e549ac74b80 100644 --- a/app/code/Magento/Store/Model/ResourceModel/Store/Collection.php +++ b/app/code/Magento/Store/Model/ResourceModel/Store/Collection.php @@ -1,6 +1,6 @@ [website_data (website_id, code, name, etc...)]] + * + * @return array + */ + public function readAllWebsites() + { + $websites = []; + $select = $this->getConnection() + ->select() + ->from($this->getTable('store_website')); + + foreach($this->getConnection()->fetchAll($select) as $websiteData) { + $websites[$websiteData['code']] = $websiteData; + } + + return $websites; + } + /** * Validate website code before object save * diff --git a/app/code/Magento/Store/Model/ResourceModel/Website/Collection.php b/app/code/Magento/Store/Model/ResourceModel/Website/Collection.php index efca779b66381..34b98cadcee73 100644 --- a/app/code/Magento/Store/Model/ResourceModel/Website/Collection.php +++ b/app/code/Magento/Store/Model/ResourceModel/Website/Collection.php @@ -1,6 +1,6 @@ _getData('website_id'); } + /** + * Reinit Stores on after save + * + * @deprecated + * @return $this + */ + public function afterSave() + { + $this->_storeManager->reinitStores(); + return parent::afterSave(); + } + /** * @inheritdoc */ @@ -1270,7 +1282,7 @@ public function getFormattedAddress() */ public function getIdentities() { - return [self::CACHE_TAG . '_' . $this->getId()]; + return [self::CACHE_TAG]; } /** diff --git a/app/code/Magento/Store/Model/StoreCookieManager.php b/app/code/Magento/Store/Model/StoreCookieManager.php index b9be73386bfb1..60453b4b44426 100644 --- a/app/code/Magento/Store/Model/StoreCookieManager.php +++ b/app/code/Magento/Store/Model/StoreCookieManager.php @@ -1,7 +1,7 @@ websiteRepository->getDefault(); - } else { + } elseif (is_numeric($websiteId)) { $website = $this->websiteRepository->getById($websiteId); + } else { + $website = $this->websiteRepository->get($websiteId); } + return $website; } @@ -224,6 +230,7 @@ public function getWebsites($withDefault = false, $codeKey = false) */ public function reinitStores() { + $this->scopeConfig->clean(); $this->currentStoreId = null; $this->storeRepository->clean(); $this->websiteRepository->clean(); diff --git a/app/code/Magento/Store/Model/StoreManagerInterface.php b/app/code/Magento/Store/Model/StoreManagerInterface.php index 385578bd7536f..22637bbe1c6ef 100644 --- a/app/code/Magento/Store/Model/StoreManagerInterface.php +++ b/app/code/Magento/Store/Model/StoreManagerInterface.php @@ -1,6 +1,6 @@ entities[$code])) { return $this->entities[$code]; } - $store = $this->storeFactory->create(); - $store->load($code, 'code'); + + $storeData = $this->getAppConfig()->get('scopes', "stores/$code", []); + $store = $this->storeFactory->create([ + 'data' => $storeData + ]); + if ($store->getId() === null) { throw new NoSuchEntityException(__('Requested store is not found')); } @@ -85,11 +101,16 @@ public function getById($id) if (isset($this->entitiesById[$id])) { return $this->entitiesById[$id]; } - $store = $this->storeFactory->create(); - $store->load($id); + + $storeData = $this->getAppConfig()->get('scopes', "stores/$id", []); + $store = $this->storeFactory->create([ + 'data' => $storeData + ]); + if ($store->getId() === null) { throw new NoSuchEntityException(__('Requested store is not found')); } + $this->entitiesById[$id] = $store; $this->entities[$store->getCode()] = $store; return $store; @@ -113,19 +134,35 @@ public function getActiveStoreById($id) */ public function getList() { - if (!$this->allLoaded) { - /** @var $storeCollection \Magento\Store\Model\ResourceModel\Store\Collection */ - $storeCollection = $this->storeCollectionFactory->create(); - $storeCollection->setLoadDefault(true); - foreach ($storeCollection as $item) { - $this->entities[$item->getCode()] = $item; - $this->entitiesById[$item->getId()] = $item; - } - $this->allLoaded = true; + if ($this->allLoaded) { + return $this->entities; + } + $stores = $this->getAppConfig()->get('scopes', "stores", []); + foreach ($stores as $data) { + $store = $this->storeFactory->create([ + 'data' => $data + ]); + $this->entities[$store->getCode()] = $store; + $this->entitiesById[$store->getId()] = $store; } + $this->allLoaded = true; return $this->entities; } + /** + * Retrieve application config. + * + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if (!$this->appConfig) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } + /** * {@inheritdoc} */ diff --git a/app/code/Magento/Store/Model/StoreResolver.php b/app/code/Magento/Store/Model/StoreResolver.php index a19d75d9f47e0..967694d5b5c56 100644 --- a/app/code/Magento/Store/Model/StoreResolver.php +++ b/app/code/Magento/Store/Model/StoreResolver.php @@ -1,6 +1,6 @@ getId()]; + return [self::CACHE_TAG]; } /** diff --git a/app/code/Magento/Store/Model/WebsiteManagement.php b/app/code/Magento/Store/Model/WebsiteManagement.php index db9b72fc6f14f..2a22fc61deeb0 100644 --- a/app/code/Magento/Store/Model/WebsiteManagement.php +++ b/app/code/Magento/Store/Model/WebsiteManagement.php @@ -1,6 +1,6 @@ entities[$code])) { return $this->entities[$code]; } - $website = $this->factory->create(); - $website->load($code, 'code'); + + $websiteData = $this->getAppConfig()->get('scopes', "websites/$code", []); + $website = $this->factory->create([ + 'data' => $websiteData + ]); + if ($website->getId() === null) { throw new NoSuchEntityException(); } @@ -78,14 +94,17 @@ public function getById($id) if (isset($this->entitiesById[$id])) { return $this->entitiesById[$id]; } - /** @var Website $website */ - $website = $this->factory->create(); - $website->load($id); + + $websiteData = $this->getAppConfig()->get('scopes', "websites/$id", []); + $website = $this->factory->create([ + 'data' => $websiteData + ]); + if ($website->getId() === null) { throw new NoSuchEntityException(); } - $this->entitiesById[$id] = $website; $this->entities[$website->getCode()] = $website; + $this->entitiesById[$id] = $website; return $website; } @@ -95,10 +114,13 @@ public function getById($id) public function getList() { if (!$this->allLoaded) { - $collection = $this->websiteCollectionFactory->create(); - $collection->setLoadDefault(true); - foreach ($collection as $item) { - $this->entities[$item->getCode()] = $item; + $websites = $this->getAppConfig()->get('scopes', 'websites', []); + foreach ($websites as $data) { + $website = $this->factory->create([ + 'data' => $data + ]); + $this->entities[$website->getCode()] = $website; + $this->entitiesById[$website->getId()] = $website; } $this->allLoaded = true; } @@ -118,23 +140,13 @@ public function getDefault() } } if (!$this->allLoaded) { - /** @var \Magento\Store\Model\ResourceModel\Website\Collection $collection */ - $collection = $this->websiteCollectionFactory->create(); - $collection->addFieldToFilter('is_default', 1); - $items = $collection->getItems(); - if (count($items) > 1) { - throw new \DomainException(__('More than one default website is defined')); - } - if (count($items) === 0) { - throw new \DomainException(__('Default website is not defined')); - } - $this->default = $collection->getFirstItem(); - $this->entities[$this->default->getCode()] = $this->default; - $this->entitiesById[$this->default->getId()] = $this->default; - } else { + $this->initDefaultWebsite(); + } + if (!$this->default) { throw new \DomainException(__('Default website is not defined')); } } + return $this->default; } @@ -148,4 +160,40 @@ public function clean() $this->default = null; $this->allLoaded = false; } + + /** + * Retrieve application config. + * + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if (!$this->appConfig) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } + + /** + * Initialize default website. + * @return void + */ + private function initDefaultWebsite() + { + $websites = (array) $this->getAppConfig()->get('scopes', 'websites', []); + foreach ($websites as $data) { + if (isset($data['is_default']) && $data['is_default'] == 1) { + if ($this->default) { + throw new \DomainException(__('More than one default website is defined')); + } + $website = $this->factory->create([ + 'data' => $data + ]); + $this->default = $website; + $this->entities[$this->default->getCode()] = $this->default; + $this->entitiesById[$this->default->getId()] = $this->default; + } + } + } } diff --git a/app/code/Magento/Store/Setup/InstallSchema.php b/app/code/Magento/Store/Setup/InstallSchema.php index b6f97993f3b78..8c7935d8d18ba 100644 --- a/app/code/Magento/Store/Setup/InstallSchema.php +++ b/app/code/Magento/Store/Setup/InstallSchema.php @@ -1,6 +1,6 @@ data = [ + 'groups' => [ + '1' => [ + 'name' => 'My Group', + 'group_id' => 1 + ], + ], + 'stores' => [ + 'myStore' => [ + 'name' => 'My Store', + 'code' => 'myStore' + ] + ], + 'websites' => [ + 'myWebsite' => [ + 'name' => 'My Website', + 'code' => 'myWebsite' + ] + ], + ]; + $this->websiteCollectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->groupCollectionFactory = $this->getMockBuilder(GroupCollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->storeCollectionFactory = $this->getMockBuilder(StoreCollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->websiteCollection = $this->getMockBuilder(WebsiteCollection::class) + ->disableOriginalConstructor() + ->setMethods(['setLoadDefault', 'getIterator']) + ->getMock(); + $this->groupCollection = $this->getMockBuilder(GroupCollection::class) + ->disableOriginalConstructor() + ->setMethods(['setLoadDefault', 'getIterator']) + ->getMock(); + $this->storeCollection = $this->getMockBuilder(StoreCollection::class) + ->disableOriginalConstructor() + ->setMethods(['setLoadDefault', 'getIterator']) + ->getMock(); + + $this->websiteFactory = $this->getMockBuilder(WebsiteFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->groupFactory = $this->getMockBuilder(GroupFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->storeFactory = $this->getMockBuilder(StoreFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->website = $this->getMockBuilder(Website::class) + ->disableOriginalConstructor() + ->getMock(); + $this->group = $this->getMockBuilder(Group::class) + ->disableOriginalConstructor() + ->getMock(); + $this->store = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->deploymentConfig = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->configSource = new RuntimeConfigSource( + $this->websiteCollectionFactory, + $this->groupCollectionFactory, + $this->storeCollectionFactory, + $this->websiteFactory, + $this->groupFactory, + $this->storeFactory, + $this->deploymentConfig + ); + } + + /** + * @param string $path + * @dataProvider getDataProvider + * @return void + */ + public function testGet($path) + { + $this->deploymentConfig->expects($this->once()) + ->method('get') + ->with('db') + ->willReturn(true); + $this->prepareWebsites($path); + $this->prepareGroups($path); + $this->prepareStores($path); + $this->assertEquals($this->getExpectedResult($path), $this->configSource->get($path)); + } + + private function getExpectedResult($path) + { + switch ($this->getScope($path)) { + case 'websites': + $result = ['websites' => $this->data['websites']]; + break; + case 'groups': + $result = ['groups' => $this->data['groups']]; + break; + case 'stores': + $result = ['stores' => $this->data['stores']]; + break; + default: + $result = $this->data; + break; + } + return $result; + } + + private function prepareStores($path) + { + $scope = $this->getScope($path); + if ($scope == 'stores' || $scope == 'default') { + if ($this->getScopeCode($path)) { + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('load') + ->with('myStore', 'code') + ->willReturnSelf(); + } else { + $this->storeCollectionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->storeCollection); + $this->storeCollection->expects($this->once()) + ->method('setLoadDefault') + ->with(true) + ->willReturnSelf(); + $this->storeCollection->expects($this->once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$this->store])); + $this->store->expects($this->once()) + ->method('getCode') + ->willReturn('myStore'); + } + $this->store->expects($this->once()) + ->method('getData') + ->willReturn($this->data['stores']['myStore']); + } + } + + private function prepareGroups($path) + { + $scope = $this->getScope($path); + if ($scope == 'groups' || $scope == 'default') { + if ($this->getScopeCode($path)) { + $this->groupFactory->expects($this->once()) + ->method('create') + ->willReturn($this->group); + $this->group->expects($this->once()) + ->method('load') + ->with($this->data['groups']['1']['group_id']) + ->willReturnSelf(); + } else { + $this->groupCollectionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->groupCollection); + $this->groupCollection->expects($this->once()) + ->method('setLoadDefault') + ->with(true) + ->willReturnSelf(); + $this->groupCollection->expects($this->once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$this->group])); + $this->group->expects($this->once()) + ->method('getId') + ->willReturn($this->data['groups']['1']['group_id']); + } + $this->group->expects($this->once()) + ->method('getData') + ->willReturn($this->data['groups']['1']); + } + } + + private function prepareWebsites($path) + { + $scope = $this->getScope($path); + if ($scope == 'websites' || $scope == 'default') { + if ($this->getScopeCode($path)) { + $this->websiteFactory->expects($this->once()) + ->method('create') + ->willReturn($this->website); + $this->website->expects($this->once()) + ->method('load') + ->with($this->data['websites']['myWebsite']['code']) + ->willReturnSelf(); + } else { + $this->websiteCollectionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->websiteCollection); + $this->websiteCollection->expects($this->once()) + ->method('setLoadDefault') + ->with(true) + ->willReturnSelf(); + $this->websiteCollection->expects($this->once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$this->website])); + $this->website->expects($this->once()) + ->method('getCode') + ->willReturn('myWebsite'); + } + $this->website->expects($this->once()) + ->method('getData') + ->willReturn($this->data['websites']['myWebsite']); + } + } + + private function getScopeCode($path) + { + return implode('/', array_slice(explode('/', $path), 1, 1)); + } + + private function getScope($path) + { + return implode('/', array_slice(explode('/', $path), 0, 1)); + } + + /** + * @return array + */ + public function getDataProvider() + { + return [ + ['websites/myWebsite'], + ['groups/1'], + ['stores/myStore'], + ['default'] + ]; + } +} diff --git a/app/code/Magento/Store/Test/Unit/App/FrontController/Plugin/RequestPreprocessorTest.php b/app/code/Magento/Store/Test/Unit/App/FrontController/Plugin/RequestPreprocessorTest.php index 287199d58396f..324c3ce6118cb 100644 --- a/app/code/Magento/Store/Test/Unit/App/FrontController/Plugin/RequestPreprocessorTest.php +++ b/app/code/Magento/Store/Test/Unit/App/FrontController/Plugin/RequestPreprocessorTest.php @@ -1,6 +1,6 @@ _processorMock = $this->getMock( - 'Magento\Store\Model\Config\Processor\Placeholder', - [], - [], - '', - false - ); - $this->_model = new \Magento\Store\Model\Config\Converter($this->_processorMock); + $this->_model = new \Magento\Store\Model\Config\Converter(); } public function testConvert() @@ -34,17 +24,6 @@ public function testConvert() 'to' => ['save' => 'saved value', 'overwrite' => 'overwritten', 'added' => 'added value'], ], ]; - $processorResult = '123Value'; - $this->_processorMock->expects( - $this->once() - )->method( - 'process' - )->with( - $mergeResult - )->will( - $this->returnValue($processorResult) - ); - - $this->assertEquals($processorResult, $this->_model->convert($source, $initial)); + $this->assertEquals($mergeResult, $this->_model->convert($source, $initial)); } } diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/PlaceholderTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/PlaceholderTest.php new file mode 100644 index 0000000000000..0e0643893207f --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/PlaceholderTest.php @@ -0,0 +1,64 @@ +_requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); + $this->_requestMock->expects( + $this->any() + )->method( + 'getDistroBaseUrl' + )->will( + $this->returnValue('http://localhost/') + ); + $this->_model = new \Magento\Store\Model\Config\Placeholder( + $this->_requestMock, + [ + 'unsecureBaseUrl' => Store::XML_PATH_UNSECURE_BASE_URL, + 'secureBaseUrl' => Store::XML_PATH_SECURE_BASE_URL + ], + \Magento\Store\Model\Store::BASE_URL_PLACEHOLDER + ); + } + + public function testProcess() + { + $data = [ + 'web' => [ + 'unsecure' => [ + 'base_url' => 'http://localhost/', + 'base_link_url' => '{{unsecure_base_url}}website/de', + ], + 'secure' => [ + 'base_url' => 'https://localhost/', + 'base_link_url' => '{{secure_base_url}}website/de', + ], + ], + 'path' => 'value', + 'some_url' => '{{base_url}}some', + ]; + $expectedResult = $data; + $expectedResult['web']['unsecure']['base_link_url'] = 'http://localhost/website/de'; + $expectedResult['web']['secure']['base_link_url'] = 'https://localhost/website/de'; + $expectedResult['some_url'] = 'http://localhost/some'; + $this->assertEquals($expectedResult, $this->_model->process($data)); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php index 04b82d2557b76..0bf2bcf682466 100644 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php @@ -1,64 +1,64 @@ _requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - $this->_requestMock->expects( + $this->configPlaceholderMock = $this->getMock('Magento\Store\Model\Config\Placeholder', [], [], '', false); + + $this->configPlaceholderMock->expects( $this->any() )->method( - 'getDistroBaseUrl' - )->will( - $this->returnValue('http://localhost/') + 'process' + )->withConsecutive( + [['key1' => 'value1']], + [['key2' => 'value2']] + )->willReturnOnConsecutiveCalls( + ['key1' => 'value1-processed'], + ['key2' => 'value2-processed'] ); - $this->_model = new \Magento\Store\Model\Config\Processor\Placeholder( - $this->_requestMock, - [ - 'unsecureBaseUrl' => Store::XML_PATH_UNSECURE_BASE_URL, - 'secureBaseUrl' => Store::XML_PATH_SECURE_BASE_URL - ], - \Magento\Store\Model\Store::BASE_URL_PLACEHOLDER + + $this->model = new \Magento\Store\Model\Config\Processor\Placeholder( + $this->getMock(\Magento\Framework\App\RequestInterface::class), + [], + null, + $this->configPlaceholderMock ); } public function testProcess() { $data = [ - 'web' => [ - 'unsecure' => [ - 'base_url' => 'http://localhost/', - 'base_link_url' => '{{unsecure_base_url}}website/de', - ], - 'secure' => [ - 'base_url' => 'https://localhost/', - 'base_link_url' => '{{secure_base_url}}website/de', - ], - ], - 'path' => 'value', - 'some_url' => '{{base_url}}some', + 'default' => ['key1' => 'value1'], + 'websites' => [ + 'code' => ['key2' => 'value2'] + ] + ]; + $expected = [ + 'default' => ['key1' => 'value1-processed'], + 'websites' => [ + 'code' => ['key2' => 'value2-processed'] + ] ]; - $expectedResult = $data; - $expectedResult['web']['unsecure']['base_link_url'] = 'http://localhost/website/de'; - $expectedResult['web']['secure']['base_link_url'] = 'https://localhost/website/de'; - $expectedResult['some_url'] = 'http://localhost/some'; - $this->assertEquals($expectedResult, $this->_model->process($data)); + + $this->assertEquals($expected, $this->model->process($data)); } } 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 deleted file mode 100644 index bc42b3299b73e..0000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php +++ /dev/null @@ -1,74 +0,0 @@ -_initialConfigMock = $this->getMock('Magento\Framework\App\Config\Initial', [], [], '', false); - $this->_collectionFactory = $this->getMock( - 'Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory', - ['create'], - [], - '', - false - ); - $this->_model = new \Magento\Store\Model\Config\Reader\DefaultReader( - $this->_initialConfigMock, - new \Magento\Framework\App\Config\Scope\Converter(), - $this->_collectionFactory - ); - } - - public function testRead() - { - $this->_initialConfigMock->expects( - $this->any() - )->method( - 'getData' - )->with( - ScopeConfigInterface::SCOPE_TYPE_DEFAULT - )->will( - $this->returnValue(['config' => ['key1' => 'default_value1', 'key2' => 'default_value2']]) - ); - $this->_collectionFactory->expects( - $this->once() - )->method( - 'create' - )->with( - ['scope' => 'default'] - )->will( - $this->returnValue( - [ - new \Magento\Framework\DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), - new \Magento\Framework\DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), - ] - ) - ); - $expectedData = [ - 'config' => ['key1' => 'default_db_value1', 'key2' => 'default_value2', 'key3' => 'default_db_value3'], - ]; - $this->assertEquals($expectedData, $this->_model->read()); - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/ReaderPoolTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/ReaderPoolTest.php deleted file mode 100644 index a5e2be7d0e1b1..0000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/ReaderPoolTest.php +++ /dev/null @@ -1,83 +0,0 @@ -_defaultReaderMock = $this->getMock( - 'Magento\Store\Model\Config\Reader\DefaultReader', [], [], '', false - ); - $this->_websiteReaderMock = $this->getMock( - 'Magento\Store\Model\Config\Reader\Website', [], [], '', false - ); - $this->_storeReaderMock = $this->getMock( - 'Magento\Store\Model\Config\Reader\Store', [], [], '', false - ); - - $this->_model = new \Magento\Store\Model\Config\Reader\ReaderPool([ - 'default' => $this->_defaultReaderMock, - 'website' => $this->_websiteReaderMock, - 'store' => $this->_storeReaderMock, - ]); - } - - /** - * @covers \Magento\Store\Model\Config\Reader\ReaderPool::getReader - * @dataProvider getReaderDataProvider - * @param string $scope - * @param string $instanceType - */ - public function testGetReader($scope, $instanceType) - { - $this->assertInstanceOf($instanceType, $this->_model->getReader($scope)); - } - - /** - * @return array - */ - public function getReaderDataProvider() - { - return [ - [ - 'scope' => 'default', - 'expectedResult' => 'Magento\Store\Model\Config\Reader\DefaultReader', - ], - [ - 'scope' => 'website', - 'expectedResult' => 'Magento\Store\Model\Config\Reader\Website' - ], - [ - 'scope' => 'store', - 'expectedResult' => 'Magento\Store\Model\Config\Reader\Store' - ], - ]; - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/DefaultScopeTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/DefaultScopeTest.php new file mode 100644 index 0000000000000..0d8387973fc85 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/DefaultScopeTest.php @@ -0,0 +1,46 @@ + 'default_db_value1', + 'config/key3' => 'default_db_value3', + ]; + $collectionFactory = $this->getMockBuilder(ScopedFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $collectionFactory->expects($this->once()) + ->method('create') + ->with(['scope' => ScopeConfigInterface::SCOPE_TYPE_DEFAULT]) + ->willReturn([ + new DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), + new DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), + ]); + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->with($expectedResult) + ->willReturnArgument(0); + $source = new DefaultScope( + $collectionFactory, + $converter + ); + $this->assertEquals($expectedResult, $source->get()); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/StoreTest.php new file mode 100644 index 0000000000000..c4e879793abf4 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/StoreTest.php @@ -0,0 +1,144 @@ +collectionFactory = $this->getMockBuilder(ScopedFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteFactory = $this->getMockBuilder(\Magento\Store\Model\WebsiteFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->website = $this->getMockBuilder(\Magento\Store\Model\Website::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteSource = $this->getMockBuilder(WebsiteSource::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->store = $this->getMockBuilder(StoreInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeSource = new StoreSource( + $this->collectionFactory, + $this->converter, + $this->websiteFactory, + $this->websiteSource, + $this->storeManager + ); + } + + public function testGet() + { + $scopeCode = 'myStore'; + $expectedResult = [ + 'config/key1' => 'default_db_value1', + 'config/key3' => 'default_db_value3', + ]; + $this->storeManager->expects($this->once()) + ->method('getStore') + ->with($scopeCode) + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->store->expects($this->once()) + ->method('getWebsiteId') + ->willReturn(1); + $this->collectionFactory->expects($this->once()) + ->method('create') + ->with(['scope' => ScopeInterface::SCOPE_STORES, 'scopeId' => 1]) + ->willReturn([ + new DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), + new DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), + ]); + $this->websiteSource->expects($this->once()) + ->method('get') + ->with(1) + ->willReturn([]); + + $this->converter->expects($this->at(0)) + ->method('convert') + ->with([ + 'config/key1' => 'default_db_value1', + 'config/key3' => 'default_db_value3' + ]) + ->willReturnArgument(0); + + $this->converter->expects($this->at(1)) + ->method('convert') + ->with($expectedResult) + ->willReturnArgument(0); + + $this->assertEquals($expectedResult, $this->storeSource->get($scopeCode)); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/WebsiteTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/WebsiteTest.php new file mode 100644 index 0000000000000..1a30a8cc7b245 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/WebsiteTest.php @@ -0,0 +1,113 @@ +collectionFactory = $this->getMockBuilder(ScopedFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteFactory = $this->getMockBuilder(\Magento\Store\Model\WebsiteFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->website = $this->getMockBuilder(\Magento\Store\Model\Website::class) + ->disableOriginalConstructor() + ->getMock(); + $this->defaultScopeReader = $this->getMockBuilder(DefaultScope::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteSource = new WebsiteSource( + $this->collectionFactory, + $this->converter, + $this->websiteFactory, + $this->defaultScopeReader + ); + } + + public function testGet() + { + $scopeCode = 'myWebsite'; + $expectedResult = [ + 'config/key1' => 'default_db_value1', + 'config/key3' => 'default_db_value3', + ]; + $this->websiteFactory->expects($this->once()) + ->method('create') + ->willReturn($this->website); + $this->website->expects($this->once()) + ->method('load') + ->with($scopeCode); + $this->website->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->collectionFactory->expects($this->once()) + ->method('create') + ->with(['scope' => ScopeInterface::SCOPE_WEBSITES, 'scopeId' => 1]) + ->willReturn([ + new DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), + new DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), + ]); + $this->defaultScopeReader->expects($this->once()) + ->method('get') + ->willReturn([]); + $this->converter->expects($this->once()) + ->method('convert') + ->with($expectedResult) + ->willReturnArgument(0); + $this->assertEquals($expectedResult, $this->websiteSource->get($scopeCode)); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/DefaultScopeTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/DefaultScopeTest.php new file mode 100644 index 0000000000000..9471994e96d65 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/DefaultScopeTest.php @@ -0,0 +1,34 @@ +getMockBuilder(\Magento\Framework\App\Config\Initial::class) + ->disableOriginalConstructor() + ->getMock(); + $initialConfig->expects($this->once()) + ->method('getData') + ->with(ScopeConfigInterface::SCOPE_TYPE_DEFAULT) + ->willReturn([]); + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->with([]) + ->willReturnArgument(0); + + $defaultSource = new DefaultScope($initialConfig, $converter); + $this->assertEquals([], $defaultSource->get()); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/StoreTest.php new file mode 100644 index 0000000000000..dd3ff75968cde --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/StoreTest.php @@ -0,0 +1,81 @@ +getMockBuilder(Initial::class) + ->disableOriginalConstructor() + ->getMock(); + $initialConfig->expects($this->once()) + ->method('getData') + ->with("stores|$scopeCode") + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ]); + $websiteSource = $this->getMockBuilder(Website::class) + ->disableOriginalConstructor() + ->getMock(); + $websiteSource->expects($this->once()) + ->method('get') + ->with($websiteCode) + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'ru_RU' + ] + ] + ]); + $storeManager = $this->getMockBuilder(StoreManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $store = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + $store->expects($this->once()) + ->method('getData') + ->with('website_code') + ->willReturn('myWebsite'); + + $storeManager->expects($this->once()) + ->method('getStore') + ->with($scopeCode) + ->willReturn($store); + + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->willReturnArgument(0); + + $storeSource = new Store($initialConfig, $websiteSource, $storeManager, $converter); + $this->assertEquals( + [ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ], + $storeSource->get($scopeCode) + ); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/WebsiteTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/WebsiteTest.php new file mode 100644 index 0000000000000..939f4c97a8b7d --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/WebsiteTest.php @@ -0,0 +1,62 @@ +getMockBuilder(Initial::class) + ->disableOriginalConstructor() + ->getMock(); + $initialConfig->expects($this->once()) + ->method('getData') + ->with("websites|$scopeCode") + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ]); + $defaultScopeReader = $this->getMockBuilder(DefaultScope::class) + ->disableOriginalConstructor() + ->getMock(); + $defaultScopeReader->expects($this->once()) + ->method('get') + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'ru_RU' + ] + ] + ]); + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->willReturnArgument(0); + + $websiteSource = new Website($initialConfig, $defaultScopeReader, $converter); + $this->assertEquals( + [ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ], + $websiteSource->get($scopeCode) + ); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/StoreTest.php deleted file mode 100644 index 1ea60e874d769..0000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/StoreTest.php +++ /dev/null @@ -1,159 +0,0 @@ -_scopePullMock = $this->getMock('Magento\Framework\App\Config\ScopePool', [], [], '', false); - $this->_storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); - $this->_initialConfigMock = $this->getMock('Magento\Framework\App\Config\Initial', [], [], '', false); - $this->_collectionFactory = $this->getMock( - 'Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory', - ['create'], - [], - '', - false - ); - $this->_storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false); - $placeholderProcessor = $this->getMock( - 'Magento\Store\Model\Config\Processor\Placeholder', - [], - [], - '', - false - ); - $placeholderProcessor->expects($this->any())->method('process')->will($this->returnArgument(0)); - $this->_model = new \Magento\Store\Model\Config\Reader\Store( - $this->_initialConfigMock, - $this->_scopePullMock, - new \Magento\Store\Model\Config\Converter($placeholderProcessor), - $this->_collectionFactory, - $this->_storeManagerMock - ); - } - - /** - * @dataProvider readDataProvider - * @param string|null $storeCode - */ - public function testRead($storeCode) - { - $websiteCode = 'default'; - $storeId = 1; - $websiteMock = $this->getMock('Magento\Store\Model\Website', [], [], '', false); - $websiteMock->expects($this->any())->method('getCode')->will($this->returnValue($websiteCode)); - $this->_storeMock->expects($this->any())->method('getWebsite')->will($this->returnValue($websiteMock)); - $this->_storeMock->expects($this->any())->method('getId')->will($this->returnValue($storeId)); - $this->_storeMock->expects($this->any())->method('getCode')->will($this->returnValue($websiteCode)); - - $dataMock = $this->getMock('Magento\Framework\App\Config\Data', [], [], '', false); - $dataMock->expects( - $this->any() - )->method( - 'getValue' - )->will( - $this->returnValue(['config' => ['key0' => 'website_value0', 'key1' => 'website_value1']]) - ); - - $dataMock->expects( - $this->once() - )->method( - 'getSource' - )->will( - $this->returnValue(['config' => ['key0' => 'website_value0', 'key1' => 'website_value1']]) - ); - $this->_scopePullMock->expects( - $this->once() - )->method( - 'getScope' - )->with( - 'website', - $websiteCode - )->will( - $this->returnValue($dataMock) - ); - - $this->_initialConfigMock->expects( - $this->once() - )->method( - 'getData' - )->with( - "stores|{$storeCode}" - )->will( - $this->returnValue(['config' => ['key1' => 'store_value1', 'key2' => 'store_value2']]) - ); - $this->_collectionFactory->expects( - $this->once() - )->method( - 'create' - )->with( - ['scope' => 'stores', 'scopeId' => $storeId] - )->will( - $this->returnValue( - [ - new \Magento\Framework\DataObject(['path' => 'config/key1', 'value' => 'store_db_value1']), - new \Magento\Framework\DataObject(['path' => 'config/key3', 'value' => 'store_db_value3']), - ] - ) - ); - - $this->_storeManagerMock - ->expects($this->any()) - ->method('getStore') - ->with($storeCode) - ->will($this->returnValue($this->_storeMock)); - $expectedData = [ - 'config' => [ - 'key0' => 'website_value0', - 'key1' => 'store_db_value1', - 'key2' => 'store_value2', - 'key3' => 'store_db_value3', - ], - ]; - $this->assertEquals($expectedData, $this->_model->read($storeCode)); - } - - public function readDataProvider() - { - return [ - ['default'], - [null], - ['code', ''] - ]; - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/WebsiteTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/WebsiteTest.php deleted file mode 100644 index b0e19c6e243fa..0000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/WebsiteTest.php +++ /dev/null @@ -1,131 +0,0 @@ -_initialConfigMock = $this->getMock('Magento\Framework\App\Config\Initial', [], [], '', false); - $this->_scopePullMock = $this->getMock('Magento\Framework\App\Config\ScopePool', [], [], '', false); - $this->_collectionFactory = $this->getMock( - 'Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory', - ['create'], - [], - '', - false - ); - $websiteFactoryMock = $this->getMock( - 'Magento\Store\Model\WebsiteFactory', - ['create'], - [], - '', - false - ); - $this->_websiteMock = $this->getMock('Magento\Store\Model\Website', [], [], '', false); - $websiteFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_websiteMock)); - - $this->_model = new \Magento\Store\Model\Config\Reader\Website( - $this->_initialConfigMock, - $this->_scopePullMock, - new \Magento\Framework\App\Config\Scope\Converter(), - $this->_collectionFactory, - $websiteFactoryMock - ); - } - - public function testRead() - { - $websiteCode = 'default'; - $websiteId = 1; - - $dataMock = $this->getMock('Magento\Framework\App\Config\Data', [], [], '', false); - $dataMock->expects( - $this->any() - )->method( - 'getValue' - )->will( - $this->returnValue(['config' => ['key0' => 'default_value0', 'key1' => 'default_value1']]) - ); - $dataMock->expects( - $this->once() - )->method( - 'getSource' - )->will( - $this->returnValue(['config' => ['key0' => 'default_value0', 'key1' => 'default_value1']]) - ); - $this->_scopePullMock->expects( - $this->once() - )->method( - 'getScope' - )->with( - 'default', - null - )->will( - $this->returnValue($dataMock) - ); - - $this->_initialConfigMock->expects( - $this->any() - )->method( - 'getData' - )->with( - "websites|{$websiteCode}" - )->will( - $this->returnValue(['config' => ['key1' => 'website_value1', 'key2' => 'website_value2']]) - ); - $this->_websiteMock->expects($this->once())->method('load')->with($websiteCode); - $this->_websiteMock->expects($this->any())->method('getId')->will($this->returnValue($websiteId)); - $this->_collectionFactory->expects( - $this->once() - )->method( - 'create' - )->with( - ['scope' => 'websites', 'scopeId' => $websiteId] - )->will( - $this->returnValue( - [ - new \Magento\Framework\DataObject(['path' => 'config/key1', 'value' => 'website_db_value1']), - new \Magento\Framework\DataObject(['path' => 'config/key3', 'value' => 'website_db_value3']), - ] - ) - ); - $expectedData = [ - 'config' => [ - 'key0' => 'default_value0', - 'key1' => 'website_db_value1', - 'key2' => 'website_value2', - 'key3' => 'website_db_value3', - ], - ]; - $this->assertEquals($expectedData, $this->_model->read($websiteCode)); - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/HstsTest.php b/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/HstsTest.php index 44d19174dc82c..51b4e1479084c 100644 --- a/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/HstsTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/HstsTest.php @@ -1,6 +1,6 @@ storeFactory = $this->getMockBuilder(StoreFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->storeCollectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->storeRepository = new StoreRepository( + $this->storeFactory, + $this->storeCollectionFactory + ); + $this->appConfigMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->initDistroList(); + } + + private function initDistroList() + { + $repositoryReflection = new \ReflectionClass($this->storeRepository); + $deploymentProperty = $repositoryReflection->getProperty('appConfig'); + $deploymentProperty->setAccessible(true); + $deploymentProperty->setValue($this->storeRepository, $this->appConfigMock); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested store is not found + */ + public function testGetWithException() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + + $this->storeRepository->get('some_code'); + } + + public function testGetWithAvailableStoreFromScope() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->expects($this->exactly(2)) + ->method('getId') + ->willReturn(1); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + + $this->assertEquals($storeMock, $this->storeRepository->get('some_code')); + } + + public function testGetByIdWithAvailableStoreFromScope() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + $storeMock->expects($this->once()) + ->method('getCode') + ->willReturn('some_code'); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->willReturn([]); + + $this->assertEquals($storeMock, $this->storeRepository->getById(1)); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested store is not found + */ + public function testGetByIdWithException() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->willReturn([]); + $this->storeRepository->getById(1); + } + + public function testGetList() + { + $storeMock1 = $this->getMock(StoreInterface::class); + $storeMock1->expects($this->once()) + ->method('getCode') + ->willReturn('some_code'); + $storeMock1->expects($this->once()) + ->method('getId') + ->willReturn(1); + $storeMock2 = $this->getMock(StoreInterface::class); + $storeMock2->expects($this->once()) + ->method('getCode') + ->willReturn('some_code_2'); + $storeMock2->expects($this->once()) + ->method('getId') + ->willReturn(2); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->willReturn([ + [ + 'code' => 'some_code' + ], + [ + 'code' => 'some_code_2' + ] + ]); + $this->storeFactory->expects($this->at(0)) + ->method('create') + ->willReturn($storeMock1); + $this->storeFactory->expects($this->at(1)) + ->method('create') + ->willReturn($storeMock2); + + $this->assertEquals( + ['some_code' => $storeMock1, 'some_code_2' => $storeMock2], + $this->storeRepository->getList() + ); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php index baff6670c84e4..f511db7638830 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreTest.php @@ -1,6 +1,6 @@ websiteFactoryMock = + $this->getMockBuilder('Magento\Store\Model\WebsiteFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); $this->websiteCollectionFactoryMock = $this->getMockBuilder('Magento\Store\Model\ResourceModel\Website\CollectionFactory') ->disableOriginalConstructor() @@ -29,26 +46,46 @@ protected function setUp() $this->model = $objectManager->getObject( 'Magento\Store\Model\WebsiteRepository', [ + 'factory' => $this->websiteFactoryMock, 'websiteCollectionFactory' => $this->websiteCollectionFactoryMock ] ); + $this->appConfigMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->initDistroList(); + } + private function initDistroList() + { + $repositoryReflection = new \ReflectionClass($this->model); + $deploymentProperty = $repositoryReflection->getProperty('appConfig'); + $deploymentProperty->setAccessible(true); + $deploymentProperty->setValue($this->model, $this->appConfigMock); } public function testGetDefault() { - $collectionMock = $this->getMockBuilder('Magento\Store\Model\ResourceModel\Website\Collection') - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); $websiteMock = $this->getMockBuilder('Magento\Store\Api\Data\WebsiteInterface') ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->websiteCollectionFactoryMock->expects($this->any())->method('create')->willReturn($collectionMock); - $collectionMock->expects($this->any())->method('addFieldToFilter'); - $collectionMock->expects($this->any())->method('getItems')->willReturn([1]); - $collectionMock->expects($this->any())->method('getFirstItem')->willReturn($websiteMock); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->with('scopes', 'websites') + ->willReturn([ + 'some_code' => [ + 'code' => 'some_code', + 'is_default' => 1 + ], + 'some_code_2' => [ + 'code' => 'some_code_2', + 'is_default' => 0 + ] + ]); + $this->websiteFactoryMock->expects($this->at(0)) + ->method('create') + ->willReturn($websiteMock); $website = $this->model->getDefault(); $this->assertInstanceOf('Magento\Store\Api\Data\WebsiteInterface', $website); @@ -61,13 +98,24 @@ public function testGetDefault() */ public function testGetDefaultIsSeveral() { - $collectionMock = $this->getMockBuilder('Magento\Store\Model\ResourceModel\Website\Collection') + $websiteMock = $this->getMockBuilder('Magento\Store\Api\Data\WebsiteInterface') ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->websiteCollectionFactoryMock->expects($this->any())->method('create')->willReturn($collectionMock); - $collectionMock->expects($this->any())->method('addFieldToFilter'); - $collectionMock->expects($this->any())->method('getItems')->willReturn([1, 2]); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->with('scopes', 'websites') + ->willReturn([ + 'some_code' => [ + 'code' => 'some_code', + 'is_default' => 1 + ], + 'some_code_2' => [ + 'code' => 'some_code_2', + 'is_default' => 1 + ] + ]); + $this->websiteFactoryMock->expects($this->any())->method('create')->willReturn($websiteMock); $this->model->getDefault(); } @@ -78,13 +126,24 @@ public function testGetDefaultIsSeveral() */ public function testGetDefaultIsZero() { - $collectionMock = $this->getMockBuilder('Magento\Store\Model\ResourceModel\Website\Collection') + $websiteMock = $this->getMockBuilder('Magento\Store\Api\Data\WebsiteInterface') ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->websiteCollectionFactoryMock->expects($this->any())->method('create')->willReturn($collectionMock); - $collectionMock->expects($this->any())->method('addFieldToFilter'); - $collectionMock->expects($this->any())->method('getItems')->willReturn([]); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->with('scopes', 'websites') + ->willReturn([ + 'some_code' => [ + 'code' => 'some_code', + 'is_default' => 0 + ], + 'some_code_2' => [ + 'code' => 'some_code_2', + 'is_default' => 0 + ] + ]); + $this->websiteFactoryMock->expects($this->any())->method('create')->willReturn($websiteMock); $this->model->getDefault(); } diff --git a/app/code/Magento/Store/Test/Unit/Model/WebsiteTest.php b/app/code/Magento/Store/Test/Unit/Model/WebsiteTest.php index 3fc39082071c8..83cfb3c63dc96 100644 --- a/app/code/Magento/Store/Test/Unit/Model/WebsiteTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/WebsiteTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Store/etc/cache.xml b/app/code/Magento/Store/etc/cache.xml index ff1664c920bdd..d291a2c953edf 100644 --- a/app/code/Magento/Store/etc/cache.xml +++ b/app/code/Magento/Store/etc/cache.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/etc/config.xml b/app/code/Magento/Store/etc/config.xml index 6bcc78be7baa4..21275effba60f 100644 --- a/app/code/Magento/Store/etc/config.xml +++ b/app/code/Magento/Store/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/etc/config.xsd b/app/code/Magento/Store/etc/config.xsd index 8ce6dc55baa67..5332a2eb60ef7 100644 --- a/app/code/Magento/Store/etc/config.xsd +++ b/app/code/Magento/Store/etc/config.xsd @@ -3,7 +3,7 @@ /** * This schema must be used to validate config.xml files * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> diff --git a/app/code/Magento/Store/etc/data_source/website.xml b/app/code/Magento/Store/etc/data_source/website.xml index bed2f68732b95..5c7ce3f15d747 100644 --- a/app/code/Magento/Store/etc/data_source/website.xml +++ b/app/code/Magento/Store/etc/data_source/website.xml @@ -1,7 +1,7 @@ @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Store/etc/di.xml b/app/code/Magento/Store/etc/di.xml index 3e9192c24d533..4a78bc14dc769 100644 --- a/app/code/Magento/Store/etc/di.xml +++ b/app/code/Magento/Store/etc/di.xml @@ -1,7 +1,7 @@ @@ -34,7 +34,7 @@ - Magento\Store\Model\Config\Reader\ReaderPool\Proxy + Magento\Framework\Config\ReaderPool\Proxy Magento\Framework\App\Cache\Type\Config @@ -43,17 +43,6 @@ store - - - Magento\Framework\App\Config\ScopePool\Proxy - - - - - Magento\Framework\App\Config\ScopePool\Proxy - Magento\Store\Model\StoreManagerInterface\Proxy - - Magento\Store\Model\StoreManagerInterface\Proxy @@ -69,18 +58,7 @@ Magento\Store\Model\StoreManagerInterface\Proxy - - - - Magento\Store\Model\Config\Reader\DefaultReader - Magento\Store\Model\Config\Reader\Website - Magento\Store\Model\Config\Reader\Website - Magento\Store\Model\Config\Reader\Store - Magento\Store\Model\Config\Reader\Store - - - - + @@ -163,7 +141,7 @@ false - + Magento\Framework\App\Request\Http\Proxy @@ -223,6 +201,7 @@ standard + frontend @@ -343,4 +322,119 @@ + + + + + DefaultScopeReader + WebsiteScopeReader + WebsiteScopeReader + StoreScopeReader + StoreScopeReader + + + + + + + + Magento\Store\Model\Config\Reader\Source\Initial\DefaultScope + false + 10 + + + Magento\Store\Model\Config\Reader\Source\Dynamic\DefaultScope + false + 100 + + + + + + + + + Magento\Store\Model\Config\Reader\Source\Initial\Website + false + 10 + + + Magento\Store\Model\Config\Reader\Source\Dynamic\Website + false + 100 + + + + + + + + + Magento\Store\Model\Config\Reader\Source\Initial\Store + false + 10 + + + Magento\Store\Model\Config\Reader\Source\Dynamic\Store + false + 100 + + + + + + + + Magento\Store\Model\Config\Processor\Placeholder + + + + + + + Magento\Store\App\Config\Type\Scopes + + + + + + scopesConfigSourceAggregatedProxy + + + + + scopesConfigSourceAggregated + + + + + + + scopesConfigInitialDataProvider + 10 + + + Magento\Store\App\Config\Source\RuntimeConfigSource + 10 + + + + + + + Magento\Framework\App\DeploymentConfig\Reader + Magento\Store\App\Config\Type\Scopes::CONFIG_TYPE + Magento\Framework\Config\File\ConfigFilePool::APP_CONFIG + + + + + + + scopesConfigSourceAggregated + Magento\Store\App\Config\Type\Scopes::CONFIG_TYPE + + + + diff --git a/app/code/Magento/Store/etc/frontend/di.xml b/app/code/Magento/Store/etc/frontend/di.xml index 598cedbe6f9a9..3e3ee0f1c5cf8 100644 --- a/app/code/Magento/Store/etc/frontend/di.xml +++ b/app/code/Magento/Store/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/etc/frontend/routes.xml b/app/code/Magento/Store/etc/frontend/routes.xml index f11b0803834f5..e5caeb8d443b1 100644 --- a/app/code/Magento/Store/etc/frontend/routes.xml +++ b/app/code/Magento/Store/etc/frontend/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/etc/frontend/sections.xml b/app/code/Magento/Store/etc/frontend/sections.xml index 8a5558c6594a8..310634efec94c 100644 --- a/app/code/Magento/Store/etc/frontend/sections.xml +++ b/app/code/Magento/Store/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/etc/module.xml b/app/code/Magento/Store/etc/module.xml index 82a723a0f3797..39dbe9a198f80 100644 --- a/app/code/Magento/Store/etc/module.xml +++ b/app/code/Magento/Store/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/etc/webapi.xml b/app/code/Magento/Store/etc/webapi.xml index a344ea26a0b94..2fa39f411002b 100644 --- a/app/code/Magento/Store/etc/webapi.xml +++ b/app/code/Magento/Store/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Store/registration.php b/app/code/Magento/Store/registration.php index 57765f3085338..fcace508c6101 100644 --- a/app/code/Magento/Store/registration.php +++ b/app/code/Magento/Store/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Swagger/etc/module.xml b/app/code/Magento/Swagger/etc/module.xml index 5d44fa84987c6..e153eade29e3c 100644 --- a/app/code/Magento/Swagger/etc/module.xml +++ b/app/code/Magento/Swagger/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swagger/registration.php b/app/code/Magento/Swagger/registration.php index e1b1babb012fa..00f77a19fa9ec 100644 --- a/app/code/Magento/Swagger/registration.php +++ b/app/code/Magento/Swagger/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml b/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml index 059fdb7fb2a8d..c0e580fa1cd49 100644 --- a/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml +++ b/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml @@ -9,7 +9,7 @@ * * The original name of this file, as part of the swagger-ui package, was dist/index.html. * - * Modified by Magento, Modifications Copyright © 2016 Magento. + * Modified by Magento, Modifications Copyright © 2013-2017 Magento, Inc. */ /** @var \Magento\Framework\View\Element\Template $block */ diff --git a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/style.css b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/style.css index 0355d2a9f2b11..b6d62f4b2f71f 100644 --- a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/style.css +++ b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/style.css @@ -1,4 +1,4 @@ -/* Modified by Magento, Modifications Copyright © 2016 Magento. */ +/* Modified by Magento, Modifications Copyright © 2013-2017 Magento, Inc. */ .swagger-section #header a#logo { font-size: 1.5em; font-weight: bold; diff --git a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/marked.js b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/marked.js index 17eefd2128395..acacdb00b56ed 100644 --- a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/marked.js +++ b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/marked.js @@ -3,7 +3,7 @@ * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) * https://github.com/chjj/marked * - * Modified by Magento, Modifications Copyright © 2016 Magento. + * Modified by Magento, Modifications Copyright © 2013-2017 Magento, Inc. */ ;(function() { diff --git a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/magento-swagger.js b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/magento-swagger.js index bca824c58a0b8..315b52c187110 100644 --- a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/magento-swagger.js +++ b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/magento-swagger.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ $(function () { diff --git a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/swagger-ui.js b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/swagger-ui.js index 6bbb257f74d49..4330f93c556bf 100644 --- a/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/swagger-ui.js +++ b/app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/swagger-ui.js @@ -6,7 +6,7 @@ * * The original name of this file, as part of the swagger-ui package, was dist/index.html. * - * Modified by Magento, Modifications Copyright © 2016 Magento. + * Modified by Magento, Modifications Copyright © 2013-2017 Magento, Inc. */ (function(){this["Handlebars"] = this["Handlebars"] || {}; this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {}; diff --git a/app/code/Magento/Swatches/Block/Adminhtml/Attribute/Edit/Options/AbstractSwatch.php b/app/code/Magento/Swatches/Block/Adminhtml/Attribute/Edit/Options/AbstractSwatch.php index 63d55a9c033fa..a8655007f60da 100644 --- a/app/code/Magento/Swatches/Block/Adminhtml/Attribute/Edit/Options/AbstractSwatch.php +++ b/app/code/Magento/Swatches/Block/Adminhtml/Attribute/Edit/Options/AbstractSwatch.php @@ -1,6 +1,6 @@ swatchHelper = $swatchHelper; $this->swatchMediaHelper = $swatchMediaHelper; - + $this->swatchAttributesProvider = $swatchAttributesProvider + ?: ObjectManager::getInstance()->get(SwatchAttributesProvider::class); parent::__construct( $context, $arrayUtils, @@ -201,6 +213,9 @@ protected function getSwatchAttributesData() } /** + * @deprecated unused + * @see isProductHasSwatchAttribute(). + * * @codeCoverageIgnore * @return void */ @@ -209,6 +224,16 @@ protected function initIsProductHasSwatchAttribute() $this->isProductHasSwatchAttribute = $this->swatchHelper->isProductHasSwatch($this->getProduct()); } + /** + * @codeCoverageIgnore + * @return bool + */ + protected function isProductHasSwatchAttribute() + { + $swatchAttributes = $this->swatchAttributesProvider->provide($this->getProduct()); + return count($swatchAttributes) > 0; + } + /** * Add Swatch Data for attribute * @@ -365,30 +390,16 @@ protected function getConfigurableOptionsIds(array $attributeData) } /** - * Produce and return block's html output + * Produce and return block's html output. * - * @codeCoverageIgnore * @return string */ - public function toHtml() + protected function _toHtml() { - $this->initIsProductHasSwatchAttribute(); $this->setTemplate( $this->getRendererTemplate() ); - - return parent::toHtml(); - } - - /** - * Return HTML code - * - * @codeCoverageIgnore - * @return string - */ - protected function _toHtml() - { - return $this->getHtmlOutput(); + return parent::_toHtml(); } /** @@ -397,11 +408,12 @@ protected function _toHtml() */ protected function getRendererTemplate() { - return $this->isProductHasSwatchAttribute ? + return $this->isProductHasSwatchAttribute() ? self::SWATCH_RENDERER_TEMPLATE : self::CONFIGURABLE_RENDERER_TEMPLATE; } /** + * @deprecated * @codeCoverageIgnore * @return string */ diff --git a/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php b/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php index 1cf97d1a278ea..1253f55b81aa3 100644 --- a/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php +++ b/app/code/Magento/Swatches/Block/Product/Renderer/Listing/Configurable.php @@ -1,6 +1,6 @@ isProductHasSwatchAttribute()) { + $output = parent::_toHtml(); + } + + return $output; + } + + /** + * @deprecated * @return string */ protected function getHtmlOutput() { $output = ''; - if ($this->isProductHasSwatchAttribute) { + if ($this->isProductHasSwatchAttribute()) { $output = parent::getHtmlOutput(); } diff --git a/app/code/Magento/Swatches/Controller/Adminhtml/Iframe/Show.php b/app/code/Magento/Swatches/Controller/Adminhtml/Iframe/Show.php index 12bf996280b1b..8397ebd28b19a 100644 --- a/app/code/Magento/Swatches/Controller/Adminhtml/Iframe/Show.php +++ b/app/code/Magento/Swatches/Controller/Adminhtml/Iframe/Show.php @@ -1,6 +1,6 @@ productCollectionFactory = $productCollectionFactory; $this->productRepository = $productRepository; $this->storeManager = $storeManager; $this->swatchCollectionFactory = $swatchCollectionFactory; $this->imageHelper = $imageHelper; + $this->swatchAttributesProvider = $swatchAttributesProvider + ?: ObjectManager::getInstance()->get(SwatchAttributesProvider::class); } /** @@ -337,14 +346,8 @@ private function getAllSizeImages(ModelProduct $product, $imageFile) */ private function getSwatchAttributes(Product $product) { - $attributes = $this->getAttributesFromConfigurable($product); - $result = []; - foreach ($attributes as $attribute) { - if ($this->isSwatchAttribute($attribute)) { - $result[] = $attribute; - } - } - return $result; + $swatchAttributes = $this->swatchAttributesProvider->provide($product); + return $swatchAttributes; } /** @@ -449,7 +452,8 @@ private function addFallbackOptions(array $fallbackValues, array $swatches) */ public function isProductHasSwatch(Product $product) { - return sizeof($this->getSwatchAttributes($product)); + $swatchAttributes = $this->getSwatchAttributes($product); + return count($swatchAttributes) > 0; } /** diff --git a/app/code/Magento/Swatches/Helper/Media.php b/app/code/Magento/Swatches/Helper/Media.php index 851938571c099..9356b2c13840d 100644 --- a/app/code/Magento/Swatches/Helper/Media.php +++ b/app/code/Magento/Swatches/Helper/Media.php @@ -1,6 +1,6 @@ cache = $cache; + $this->resourceConnection = $resourceConnection; + $this->cacheKey = $cacheKey; + $this->cacheTags = $cacheTags; + } + + /** + * Returns list of known swatch attribute codes. Check cache and database. + * + * @return array + */ + public function getCodes() + { + if ($this->swatchAttributeCodes === null) { + $swatchAttributeCodesCache = $this->cache->load($this->cacheKey); + if (false === $swatchAttributeCodesCache) { + $swatchAttributeCodes = $this->loadSwatchAttributeCodes(); + $this->cache->save(json_encode($swatchAttributeCodes), $this->cacheKey, $this->cacheTags); + } else { + $swatchAttributeCodes = json_decode($swatchAttributeCodesCache, true); + } + $this->swatchAttributeCodes = $swatchAttributeCodes; + } + + return $this->swatchAttributeCodes; + } + + /** + * Returns list of known swatch attributes. + * + * @return array + */ + private function loadSwatchAttributeCodes() + { + $select = $this->resourceConnection->getConnection()->select() + ->from( + ['a' => $this->resourceConnection->getTableName('eav_attribute')], + [ + 'attribute_id' => 'a.attribute_id', + 'attribute_code' => 'a.attribute_code', + ] + )->where( + 'a.attribute_id IN (?)', + new \Zend_Db_Expr(sprintf('(%s)', $this->getAttributeIdsSelect())) + ); + $result = $this->resourceConnection->getConnection()->fetchPairs($select); + return $result; + } + + /** + * Returns Select for attributes Ids. + * + * @return Select + */ + private function getAttributeIdsSelect() + { + return $this->resourceConnection->getConnection()->select() + ->from( + ['o' => $this->resourceConnection->getTableName('eav_attribute_option')], + ['attribute_id' => 'o.attribute_id'] + )->join( + ['s' => $this->resourceConnection->getTableName('eav_attribute_option_swatch')], + 'o.option_id = s.option_id', + [] + ); + } +} diff --git a/app/code/Magento/Swatches/Model/SwatchAttributesProvider.php b/app/code/Magento/Swatches/Model/SwatchAttributesProvider.php new file mode 100644 index 0000000000000..e0d435d8b838c --- /dev/null +++ b/app/code/Magento/Swatches/Model/SwatchAttributesProvider.php @@ -0,0 +1,69 @@ + Attribute[]] + */ + private $attributesPerProduct; + + /** + * @param Configurable $typeConfigurable + * @param SwatchAttributeCodes $swatchAttributeCodes + */ + public function __construct( + Configurable $typeConfigurable, + SwatchAttributeCodes $swatchAttributeCodes + ) { + $this->typeConfigurable = $typeConfigurable; + $this->swatchAttributeCodes = $swatchAttributeCodes; + } + + /** + * Provide list of swatch attributes for product. If product is not configurable return empty array. + * + * @param Product $product + * @return Attribute[] + */ + public function provide(Product $product) + { + if ($product->getTypeId() !== Configurable::TYPE_CODE) { + return []; + } + if (!isset($this->attributesPerProduct[$product->getId()])) { + $configurableAttributes = $this->typeConfigurable->getConfigurableAttributes($product); + $swatchAttributeIds = array_keys($this->swatchAttributeCodes->getCodes()); + $swatchAttributes = []; + foreach ($configurableAttributes as $configurableAttribute) { + if (in_array($configurableAttribute->getAttributeId(), $swatchAttributeIds)) { + $swatchAttributes[$configurableAttribute->getAttributeId()] + = $configurableAttribute->getProductAttribute(); + } + } + $this->attributesPerProduct[$product->getId()] = $swatchAttributes; + } + return $this->attributesPerProduct[$product->getId()]; + } +} diff --git a/app/code/Magento/Swatches/Observer/AddFieldsToAttributeObserver.php b/app/code/Magento/Swatches/Observer/AddFieldsToAttributeObserver.php index bd263edf9c359..95fd4d5bbcb7a 100644 --- a/app/code/Magento/Swatches/Observer/AddFieldsToAttributeObserver.php +++ b/app/code/Magento/Swatches/Observer/AddFieldsToAttributeObserver.php @@ -1,6 +1,6 @@ getMock('\Magento\Catalog\Model\Product', [], [], '', false); - $product1->expects($this->atLeastOnce())->method('isSaleable')->willReturn(true); $product1->expects($this->atLeastOnce())->method('getData')->with('code')->willReturn(1); $product2 = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); - $product2->expects($this->atLeastOnce())->method('isSaleable')->willReturn(true); $product2->expects($this->atLeastOnce())->method('getData')->with('code')->willReturn(3); $simpleProducts = [$product1, $product2]; @@ -169,7 +167,7 @@ private function prepareGetJsonSwatchConfig() '', false ); - $configurableType->expects($this->atLeastOnce())->method('getUsedProducts')->with($this->product, null) + $configurableType->expects($this->atLeastOnce())->method('getSalableUsedProducts')->with($this->product, null) ->willReturn($simpleProducts); $this->product->expects($this->any())->method('getTypeInstance')->willReturn($configurableType); diff --git a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php index e22ca83293ede..8a8580b74467d 100644 --- a/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Block/Product/Renderer/Listing/ConfigurableTest.php @@ -1,14 +1,16 @@ arrayUtils = $this->getMock('\Magento\Framework\Stdlib\ArrayUtils', [], [], '', false); - $this->jsonEncoder = $this->getMock('\Magento\Framework\Json\EncoderInterface', [], [], '', false); - $this->helper = $this->getMock('\Magento\ConfigurableProduct\Helper\Data', [], [], '', false); - $this->swatchHelper = $this->getMock('\Magento\Swatches\Helper\Data', [], [], '', false); - $this->swatchMediaHelper = $this->getMock('\Magento\Swatches\Helper\Media', [], [], '', false); - $this->catalogProduct = $this->getMock('\Magento\Catalog\Helper\Product', [], [], '', false); - $this->currentCustomer = $this->getMock('\Magento\Customer\Helper\Session\CurrentCustomer', [], [], '', false); - $this->priceCurrency = $this->getMock('\Magento\Framework\Pricing\PriceCurrencyInterface', [], [], '', false); + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->arrayUtils = $this->getMock(\Magento\Framework\Stdlib\ArrayUtils::class, [], [], '', false); + $this->jsonEncoder = $this->getMock(\Magento\Framework\Json\EncoderInterface::class, [], [], '', false); + $this->helper = $this->getMock(\Magento\ConfigurableProduct\Helper\Data::class, [], [], '', false); + $this->swatchHelper = $this->getMock(\Magento\Swatches\Helper\Data::class, [], [], '', false); + $this->swatchMediaHelper = $this->getMock(\Magento\Swatches\Helper\Media::class, [], [], '', false); + $this->catalogProduct = $this->getMock(\Magento\Catalog\Helper\Product::class, [], [], '', false); + $this->currentCustomer = $this->getMock( + \Magento\Customer\Helper\Session\CurrentCustomer::class, + [], + [], + '', + false + ); + $this->priceCurrency = $this->getMock( + \Magento\Framework\Pricing\PriceCurrencyInterface::class, + [], + [], + '', + false + ); $this->configurableAttributeData = $this->getMock( - 'Magento\ConfigurableProduct\Model\ConfigurableAttributeData', + \Magento\ConfigurableProduct\Model\ConfigurableAttributeData::class, + [], + [], + '', + false + ); + $this->product = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); + $this->typeInstance = $this->getMock( + \Magento\Catalog\Model\Product\Type\AbstractType::class, [], [], '', false ); - $this->product = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); - $this->typeInstance = $this->getMock('\Magento\Catalog\Model\Product\Type\AbstractType', [], [], '', false); - $this->scopeConfig = $this->getMock('\Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false); - $this->imageHelper = $this->getMock('\Magento\Catalog\Helper\Image', [], [], '', false); - $this->urlBuilder = $this->getMock('\Magento\Framework\UrlInterface'); + $this->scopeConfig = $this->getMock( + \Magento\Framework\App\Config\ScopeConfigInterface::class, + [], + [], + '', + false + ); + $this->imageHelper = $this->getMock(\Magento\Catalog\Helper\Image::class, [], [], '', false); + $this->urlBuilder = $this->getMock(\Magento\Framework\UrlInterface::class); + + $this->swatchAttributesProvider = self::getMockBuilder(SwatchAttributesProvider::class) + ->setMethods(['provide']) + ->disableOriginalConstructor() + ->getMock(); + + $this->contextMock = self::getMockBuilder(\Magento\Catalog\Block\Product\Context::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->eventManager = self::getMockBuilder(\Magento\Framework\Event\Manager::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->resolver = self::getMockBuilder(\Magento\Framework\View\Element\Template\File\Resolver::class) + ->setMethods(['getTemplateFileName']) + ->disableOriginalConstructor() + ->getMock(); + + $this->cacheState = self::getMockBuilder(\Magento\Framework\App\Cache\StateInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->directory = self::getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->validator = self::getMockBuilder(\Magento\Framework\View\Element\Template\File\Validator::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->templateEnginePool = self::getMockBuilder( + \Magento\Framework\View\TemplateEnginePool::class + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->contextMock->expects($this->once())->method('getResolver')->willReturn($this->resolver); + $this->contextMock->expects($this->once())->method('getEventManager')->willReturn($this->eventManager); + $this->contextMock->expects($this->once())->method('getScopeConfig')->willReturn($this->scopeConfig); + $this->contextMock->expects($this->once())->method('getCacheState')->willReturn($this->cacheState); + $this->contextMock->expects($this->once())->method('getValidator')->willReturn($this->validator); + $this->contextMock->expects($this->once())->method('getEnginePool')->willReturn($this->templateEnginePool); - $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->configurable = $objectManagerHelper->getObject( - '\Magento\Swatches\Block\Product\Renderer\Listing\Configurable', + \Magento\Swatches\Block\Product\Renderer\Listing\Configurable::class, [ + 'context' => $this->contextMock, 'scopeConfig' => $this->scopeConfig, 'imageHelper' => $this->imageHelper, 'urlBuilder' => $this->urlBuilder, @@ -96,9 +194,12 @@ public function setUp() 'currentCustomer' => $this->currentCustomer, 'priceCurrency' => $this->priceCurrency, 'configurableAttributeData' => $this->configurableAttributeData, + 'swatchAttributesProvider' => $this->swatchAttributesProvider, 'data' => [], ] ); + + $objectManagerHelper->setBackwardCompatibleProperty($this->configurable, 'directory', $this->directory); } /** @@ -176,34 +277,42 @@ public function testGetJsonSwatchUsedInProductListing() $this->configurable->getJsonSwatchConfig(); } + /** + * @return void + */ private function prepareGetJsonSwatchConfig() { - $product1 = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); - $product1->expects($this->atLeastOnce())->method('isSaleable')->willReturn(true); + $product1 = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); $product1->expects($this->any())->method('getData')->with('code')->willReturn(1); - $product2 = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); - $product2->expects($this->atLeastOnce())->method('isSaleable')->willReturn(true); + $product2 = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); $product2->expects($this->any())->method('getData')->with('code')->willReturn(3); $simpleProducts = [$product1, $product2]; $configurableType = $this->getMock( - '\Magento\ConfigurableProduct\Model\Product\Type\Configurable', + \Magento\ConfigurableProduct\Model\Product\Type\Configurable::class, [], [], '', false ); - $configurableType->expects($this->atLeastOnce())->method('getUsedProducts')->with($this->product, null) + $configurableType->expects($this->atLeastOnce())->method('getSalableUsedProducts') + ->with($this->product, null) ->willReturn($simpleProducts); $this->product->expects($this->any())->method('getTypeInstance')->willReturn($configurableType); - $productAttribute1 = $this->getMock('\Magento\Eav\Model\Entity\Attribute\AbstractAttribute', [], [], '', false); + $productAttribute1 = $this->getMock( + \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class, + [], + [], + '', + false + ); $productAttribute1->expects($this->any())->method('getId')->willReturn(1); $productAttribute1->expects($this->any())->method('getAttributeCode')->willReturn('code'); $attribute1 = $this->getMock( - '\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute', + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute::class, ['getProductAttribute'], [], '', @@ -214,4 +323,72 @@ private function prepareGetJsonSwatchConfig() $this->helper->expects($this->any())->method('getAllowAttributes')->with($this->product) ->willReturn([$attribute1]); } + + /** + * @return void + */ + public function testToHtmlNoSwatches() + { + $this->swatchAttributesProvider->expects(self::atLeastOnce()) + ->method('provide') + ->with($this->product) + ->willReturn([]); + + $this->configurable->setProduct($this->product); + + self::assertEmpty($this->configurable->toHtml()); + } + + /** + * @return void + */ + public function testToHtmlSwatches() + { + $attribute = self::getMockBuilder( + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute::class + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->swatchAttributesProvider->expects(self::atLeastOnce()) + ->method('provide') + ->with($this->product) + ->willReturn([$attribute]); + + $engine = self::getMockBuilder(\Magento\Framework\View\TemplateEngineInterface::class) + ->getMockForAbstractClass(); + + $engine->expects(self::atLeastOnce()) + ->method('render') + ->with($this->configurable, 'product/listing/renderer.phtml') + ->willReturn('
  • Swatches listing
  • '); + + $this->templateEnginePool->expects(self::atLeastOnce()) + ->method('get') + ->withAnyParameters() + ->willReturn($engine); + + $this->configurable->setProduct($this->product); + $this->configurable->setTemplate('product/listing/renderer.phtml'); + $this->configurable->setArea('frontend'); + + $this->resolver->expects(self::atLeastOnce()) + ->method('getTemplateFileName') + ->willReturn('product/listing/renderer.phtml'); + + $this->directory->expects(self::atLeastOnce()) + ->method('getRelativePath') + ->with('product/listing/renderer.phtml') + ->willReturn('product/listing/renderer.phtml'); + + $this->validator->expects(self::atLeastOnce()) + ->method('isValid') + ->with('product/listing/renderer.phtml') + ->willReturn(true); + + $html = $this->configurable->toHtml(); + + self::assertNotEmpty($html); + self::assertEquals('
  • Swatches listing
  • ', $html); + } } diff --git a/app/code/Magento/Swatches/Test/Unit/Controller/Adminhtml/Iframe/ShowTest.php b/app/code/Magento/Swatches/Test/Unit/Controller/Adminhtml/Iframe/ShowTest.php index ab80706a5f02a..ef34874ba2064 100644 --- a/app/code/Magento/Swatches/Test/Unit/Controller/Adminhtml/Iframe/ShowTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Controller/Adminhtml/Iframe/ShowTest.php @@ -1,6 +1,6 @@ objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->imageHelperMock = $this->getMock('\Magento\Catalog\Helper\Image', [], [], '', false); + $this->imageHelperMock = $this->getMock(\Magento\Catalog\Helper\Image::class, [], [], '', false); $this->productCollectionFactoryMock = $this->getMock( - '\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory', + \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class, ['create'], [], '', false ); - $this->productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); + $this->productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); $this->productCollectionMock = $this->objectManager->getCollectionMock( - '\Magento\Catalog\Model\ResourceModel\Product\Collection', + \Magento\Catalog\Model\ResourceModel\Product\Collection::class, [ $this->productMock, $this->productMock, @@ -67,35 +73,55 @@ protected function setUp() ); $this->configurableMock = $this->getMock( - '\Magento\ConfigurableProduct\Model\Product\Type\Configurable', + \Magento\ConfigurableProduct\Model\Product\Type\Configurable::class, [], [], '', false ); $this->productModelFactoryMock = $this->getMock( - '\Magento\Catalog\Model\ProductFactory', + \Magento\Catalog\Model\ProductFactory::class, ['create'], [], '', false ); - $this->productRepoMock = $this->getMock('\Magento\Catalog\Api\ProductRepositoryInterface', [], [], '', false); + $this->productRepoMock = $this->getMock( + \Magento\Catalog\Api\ProductRepositoryInterface::class, + [], + [], + '', + false + ); - $this->storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManager', [], [], '', false); + $this->storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManager::class, [], [], '', false); $this->swatchCollectionFactoryMock = $this->getMock( - '\Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory', + \Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory::class, ['create'], [], '', false ); - $this->attributeMock = $this->getMock('\Magento\Catalog\Model\ResourceModel\Eav\Attribute', [], [], '', false); + $this->attributeMock = $this->getMock( + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, + [], + [], + '', + false + ); + + $this->swatchAttributesProviderMock = $this->getMock( + \Magento\Swatches\Model\SwatchAttributesProvider::class, + ['provide'], + [], + '', + false + ); $this->swatchHelperObject = $this->objectManager->getObject( - '\Magento\Swatches\Helper\Data', + \Magento\Swatches\Helper\Data::class, [ 'productCollectionFactory' => $this->productCollectionFactoryMock, 'configurable' => $this->configurableMock, @@ -103,6 +129,7 @@ protected function setUp() 'storeManager' => $this->storeManagerMock, 'swatchCollectionFactory' => $this->swatchCollectionFactoryMock, 'imageHelper' => $this->imageHelperMock, + 'swatchAttributesProvider' => $this->swatchAttributesProviderMock, ] ); } @@ -114,6 +141,7 @@ public function dataForAdditionalData() 'update_product_preview_image' => 1, 'use_product_image_for_swatch' => 0 ]; + return [ [ serialize($additionalData), @@ -165,6 +193,7 @@ public function dataForAssembleEavAttribute() 'update_product_preview_image' => 1, 'use_product_image_for_swatch' => 0 ]; + return [ [ serialize($additionalData), @@ -198,7 +227,7 @@ public function testLoadFirstVariationWithSwatchImage($imageTypes, $expected, $r if ($expected === false) { $this->assertFalse($result); } else { - $this->assertInstanceOf('\Magento\Catalog\Model\Product', $result); + $this->assertInstanceOf(\Magento\Catalog\Model\Product::class, $result); } } @@ -212,7 +241,7 @@ public function dataForVariationWithSwatchImage() 'thumbnail' => '/m/a/magento.png', 'swatch_image' => '/m/a/magento.png', //important ], - '\Magento\Catalog\Model\Product', + \Magento\Catalog\Model\Product::class, ['color' => 31] ], [ @@ -257,7 +286,7 @@ public function testLoadFirstVariationWithImage($imageTypes, $expected, $require if ($expected === false) { $this->assertFalse($result); } else { - $this->assertInstanceOf('\Magento\Catalog\Model\Product', $result); + $this->assertInstanceOf(\Magento\Catalog\Model\Product::class, $result); } } @@ -271,7 +300,7 @@ public function dataForVariationWithImage() 'thumbnail' => '/m/a/magento.png', 'swatch_image' => '/m/a/magento.png', ], - '\Magento\Catalog\Model\Product', + \Magento\Catalog\Model\Product::class, ['color' => 31] ], [ @@ -336,9 +365,9 @@ public function testGetProductMediaGallery($mediaGallery, $image) ->with(95) ->willReturn($this->productMock); - $mediaObject = $this->getMock('\Magento\Framework\DataObject', [], [], '', false); + $mediaObject = $this->getMock(\Magento\Framework\DataObject::class, [], [], '', false); $iterator = new \ArrayIterator([$mediaObject]); - $mediaCollectionMock = $this->getMock('\Magento\Framework\Data\Collection', [], [], '', false); + $mediaCollectionMock = $this->getMock(\Magento\Framework\Data\Collection::class, [], [], '', false); $mediaCollectionMock->expects($this->any())->method('getIterator')->willReturn($iterator); $mediaObject->method('getData')->withConsecutive( ['value_id'], @@ -382,8 +411,11 @@ public function dataForMediaGallery() protected function getSwatchAttributes() { $this->getAttributesFromConfigurable(); - $this->attributeMock->method('hasData')->with('swatch_input_type')->willReturn(true); - $this->attributeMock->method('getData')->with('swatch_input_type')->willReturn('visual'); + $returnFromProvideMethod = [$this->attributeMock]; + $this->swatchAttributesProviderMock + ->method('provide') + ->with($this->productMock) + ->willReturn($returnFromProvideMethod); } protected function getUsedProducts(array $attributes) @@ -393,10 +425,10 @@ protected function getUsedProducts(array $attributes) ->method('getTypeInstance') ->willReturn($this->configurableMock); - $product1 = $this->getMock('\Magento\Catalog\Model\Product', ['hasData'], [], '', false); + $product1 = $this->getMock(\Magento\Catalog\Model\Product::class, ['hasData'], [], '', false); $product1->setData($attributes); - $product2 = $this->getMock('\Magento\Catalog\Model\Product', ['hasData'], [], '', false); + $product2 = $this->getMock(\Magento\Catalog\Model\Product::class, ['hasData'], [], '', false); $product2->setData($attributes); $simpleProducts = [$product2, $product1]; @@ -408,13 +440,8 @@ protected function getUsedProducts(array $attributes) protected function getAttributesFromConfigurable() { - $this->productMock - ->expects($this->atLeastOnce()) - ->method('getTypeInstance') - ->willReturn($this->configurableMock); - $confAttribute = $this->getMock( - '\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute', + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute::class, [], [], '', @@ -451,7 +478,7 @@ protected function addfilterByParent() ->with('catalog_product_relation') ->willReturn('catalog_product_relation'); - $zendDbSelectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $zendDbSelectMock = $this->getMock(\Magento\Framework\DB\Select::class, [], [], '', false); $this->productCollectionMock->method('getSelect')->willReturn($zendDbSelectMock); $zendDbSelectMock->method('join')->willReturn($zendDbSelectMock); @@ -460,7 +487,7 @@ protected function addfilterByParent() public function dataForCreateSwatchProduct() { - $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); + $productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); return [ [ @@ -496,7 +523,7 @@ public function dataForCreateSwatchProduct() public function dataForCreateSwatchProductByFallback() { - $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); + $productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); return [ [ @@ -513,49 +540,27 @@ public function dataForCreateSwatchProductByFallback() */ public function testGetSwatchAttributesAsArray($optionsArray, $attributeData, $expected) { - $configurable = $this->getMock( - '\Magento\ConfigurableProduct\Model\Product\Type\Configurable', - [], - [], - '', - false - ); + $this->swatchAttributesProviderMock + ->method('provide') + ->with($this->productMock) + ->willReturn([$this->attributeMock]); - $this->productMock - ->expects($this->atLeastOnce()) - ->method('getTypeInstance') - ->willReturn($configurable); + $storeId = 1; - $confAttribute = $this->getMock( - '\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute', + $this->attributeMock->method('setStoreId')->with($storeId)->will($this->returnSelf()); + $storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); + $storeMock->method('getId')->willReturn($storeId); + $this->storeManagerMock->method('getStore')->willReturn($storeMock); + + $this->attributeMock->method('getData')->with('')->willReturn($attributeData); + + $sourceMock = $this->getMock( + \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource::class, [], [], '', false ); - - $configurable - ->expects($this->atLeastOnce()) - ->method('getConfigurableAttributes') - ->with($this->productMock) - ->willReturn([$confAttribute]); - - $confAttribute - ->expects($this->atLeastOnce()) - ->method('__call') - ->with('getProductAttribute') - ->willReturn($this->attributeMock); - - $this->attributeMock->method('setStoreId')->will($this->returnSelf()); - $storeMock = $this->getMock('\Magento\Store\Model\Store', [], [], '', false); - $storeMock->method('getId')->willReturn(1); - $this->storeManagerMock->method('getStore')->willReturn($storeMock); - - $this->attributeMock->method('hasData')->with('swatch_input_type')->willReturn(true); - $this->attributeMock->expects($this->at(1))->method('getData')->with('swatch_input_type')->willReturn('visual'); - $this->attributeMock->expects($this->at(3))->method('getData')->with('')->willReturn($attributeData); - - $sourceMock = $this->getMock('\Magento\Eav\Model\Entity\Attribute\Source\AbstractSource', [], [], '', false); $sourceMock->expects($this->any())->method('getAllOptions')->with(false)->willReturn($optionsArray); $this->attributeMock->method('getSource')->willReturn($sourceMock); @@ -611,7 +616,7 @@ public function dataForGettingSwatchAsArray() public function testGetSwatchesByOptionsIdIf1() { - $swatchMock = $this->getMock('\Magento\Swatches\Model\Swatch', [], [], '', false); + $swatchMock = $this->getMock(\Magento\Swatches\Model\Swatch::class, [], [], '', false); $optionsData = [ [ @@ -628,7 +633,7 @@ public function testGetSwatchesByOptionsIdIf1() $swatchMock->expects($this->at(2))->method('getData')->with('')->willReturn($optionsData[0]); $swatchCollectionMock = $this->objectManager->getCollectionMock( - '\Magento\Swatches\Model\ResourceModel\Swatch\Collection', + \Magento\Swatches\Model\ResourceModel\Swatch\Collection::class, [ $swatchMock, ] @@ -637,7 +642,7 @@ public function testGetSwatchesByOptionsIdIf1() $swatchCollectionMock->method('addFilterByOptionsIds')->with([35])->will($this->returnSelf()); - $storeMock = $this->getMock('\Magento\Store\Model\Store', [], [], '', false); + $storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); $this->storeManagerMock->method('getStore')->willReturn($storeMock); $storeMock->method('getId')->willReturn(1); @@ -646,7 +651,7 @@ public function testGetSwatchesByOptionsIdIf1() public function testGetSwatchesByOptionsIdIf2() { - $swatchMock = $this->getMock('\Magento\Swatches\Model\Swatch', [], [], '', false); + $swatchMock = $this->getMock(\Magento\Swatches\Model\Swatch::class, [], [], '', false); $optionsData = [ [ @@ -677,7 +682,7 @@ public function testGetSwatchesByOptionsIdIf2() $swatchMock->expects($this->at(9))->method('getData')->with('')->willReturn($optionsData[1]); $swatchCollectionMock = $this->objectManager->getCollectionMock( - '\Magento\Swatches\Model\ResourceModel\Swatch\Collection', + \Magento\Swatches\Model\ResourceModel\Swatch\Collection::class, [ $swatchMock, $swatchMock, @@ -687,7 +692,7 @@ public function testGetSwatchesByOptionsIdIf2() $swatchCollectionMock->method('addFilterByOptionsIds')->with([35])->will($this->returnSelf()); - $storeMock = $this->getMock('\Magento\Store\Model\Store', [], [], '', false); + $storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); $this->storeManagerMock->method('getStore')->willReturn($storeMock); $storeMock->method('getId')->willReturn(1); @@ -696,7 +701,7 @@ public function testGetSwatchesByOptionsIdIf2() public function testGetSwatchesByOptionsIdIf3() { - $swatchMock = $this->getMock('\Magento\Swatches\Model\Swatch', [], [], '', false); + $swatchMock = $this->getMock(\Magento\Swatches\Model\Swatch::class, [], [], '', false); $optionsData = [ 'type' => 0, @@ -713,7 +718,7 @@ public function testGetSwatchesByOptionsIdIf3() $swatchMock->expects($this->at(4))->method('getData')->with('')->willReturn($optionsData); $swatchCollectionMock = $this->objectManager->getCollectionMock( - '\Magento\Swatches\Model\ResourceModel\Swatch\Collection', + \Magento\Swatches\Model\ResourceModel\Swatch\Collection::class, [ $swatchMock, ] @@ -722,7 +727,7 @@ public function testGetSwatchesByOptionsIdIf3() $swatchCollectionMock->method('addFilterByOptionsIds')->with([35])->will($this->returnSelf()); - $storeMock = $this->getMock('\Magento\Store\Model\Store', [], [], '', false); + $storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); $this->storeManagerMock->method('getStore')->willReturn($storeMock); $storeMock->method('getId')->willReturn(1); @@ -733,7 +738,7 @@ public function testIsProductHasSwatch() { $this->getSwatchAttributes(); $result = $this->swatchHelperObject->isProductHasSwatch($this->productMock); - $this->assertEquals(2, $result); + $this->assertEquals(true, $result); } /** @@ -803,6 +808,7 @@ public function dataForIsVisualSwatchType() 'update_product_preview_image' => 1, 'use_product_image_for_swatch' => 0 ]; + return [ [ serialize($additionalData), @@ -859,6 +865,7 @@ public function dataForIsTextSwatchType() 'update_product_preview_image' => 1, 'use_product_image_for_swatch' => 0 ]; + return [ [ serialize($additionalData), diff --git a/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php b/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php index 83333a3dbca2b..7c561dae973e1 100644 --- a/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Helper/MediaTest.php @@ -1,6 +1,6 @@ swatchesHelperMock = $this->getMock( - '\Magento\Swatches\Helper\Data', - ['loadVariationByFallback', 'isSwatchAttribute'], + \Magento\Swatches\Helper\Data::class, + ['loadVariationByFallback', 'isSwatchAttribute', 'isProductHasSwatch'], [], '', false ); $this->attributeFactoryMock = $this->getMock( - '\Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory', + \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory::class, ['create'], [], '', @@ -50,7 +50,7 @@ protected function setUp() ); $this->eavConfigMock = $this->getMock( - '\Magento\Eav\Model\Config', + \Magento\Eav\Model\Config::class, [], [], '', @@ -58,20 +58,20 @@ protected function setUp() ); $this->attributeMock = $this->getMock( - '\Magento\Catalog\Model\ResourceModel\Eav\Attribute', + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, ['loadByCode', 'getId', 'getUsedInProductListing', 'getIsFilterable', 'getData'], [], '', false ); - $this->requestMock = $this->getMock('\Magento\Framework\App\Request\Http', ['getParams'], [], '', false); - $this->productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); + $this->requestMock = $this->getMock(\Magento\Framework\App\Request\Http::class, ['getParams'], [], '', false); + $this->productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->pluginModel = $objectManager->getObject( - 'Magento\Swatches\Model\Plugin\ProductImage', + \Magento\Swatches\Model\Plugin\ProductImage::class, [ 'swatchesHelperData' => $this->swatchesHelperMock, 'eavConfig' => $this->eavConfigMock, @@ -98,8 +98,12 @@ public function testBeforeGetImage($expected) ->expects($this->exactly($expected['loadVariationByFallback_count'])) ->method('loadVariationByFallback') ->willReturn($expected['product']); + $this->swatchesHelperMock + ->method('isProductHasSwatch') + ->with($this->productMock) + ->willReturn(false); - $productImageMock = $this->getMock('Magento\Catalog\Block\Product\AbstractProduct', [], [], '', false); + $productImageMock = $this->getMock(\Magento\Catalog\Block\Product\AbstractProduct::class, [], [], '', false); $result = $this->pluginModel->beforeGetImage($productImageMock, $this->productMock, $expected['page_handle']); $this->assertEquals([$this->productMock, $expected['page_handle'], []], $result); @@ -155,7 +159,7 @@ protected function canReplaceImageWithSwatch($expected) */ public function dataForTest() { - $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); + $productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false); $productMock->expects($this->any())->method('getImage')->willReturn(false); return [ diff --git a/app/code/Magento/Swatches/Test/Unit/Model/Plugin/ProductTest.php b/app/code/Magento/Swatches/Test/Unit/Model/Plugin/ProductTest.php index 2f6a601fd40f9..1fedea1bd7a5e 100644 --- a/app/code/Magento/Swatches/Test/Unit/Model/Plugin/ProductTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Model/Plugin/ProductTest.php @@ -1,6 +1,6 @@ 'text_swatch', + 11 => 'image_swatch' + ]; + + protected function setUp() + { + $this->cache = $this->getMock( + CacheInterface::class, + [ + 'getFrontend', + 'load', + 'save', + 'remove', + 'clean' + ], + [], + '', + false + ); + + $this->resourceConnection = $this->getMock( + ResourceConnection::class, + ['getConnection', 'getTableName'], + [], + '', + false + ); + + $cacheTags = [Attribute::CACHE_TAG]; + + $this->swatchAttributeCodesModel = new SwatchAttributeCodes( + $this->cache, + $this->resourceConnection, + self::CACHE_KEY, + $cacheTags + ); + } + + /** + * @dataProvider dataForGettingCodes + */ + public function testGetCodes($swatchAttributeCodesCache, $expected) + { + $this->cache + ->method('load') + ->with(self::CACHE_KEY) + ->willReturn($swatchAttributeCodesCache); + + $adapterMock = $this->getMock( + Mysql::class, + ['select', 'fetchPairs'], + [], + '', + false + ); + + $selectMock = $this->getMock( + Select::class, + ['from', 'where', 'join'], + [], + '', + false + ); + $selectMock + ->method('from') + ->withConsecutive( + [ + self::identicalTo( + ['a' => self::ATTRIBUTE_TABLE], + [ + 'attribute_id' => 'a.attribute_id', + 'attribute_code' => 'a.attribute_code', + ] + ) + ], + [ + self::identicalTo( + ['o' => self::ATTRIBUTE_OPTION_TABLE], + ['attribute_id' => 'o.attribute_id'] + ) + ] + ) + ->willReturnSelf(); + + //used anything for second argument because of new \Zend_Db_Expt used in code. + $selectMock->method('where') + ->with( + self::identicalTo('a.attribute_id IN (?)'), + self::anything() + ) + ->willReturnSelf(); + + $adapterMock->method('select') + ->willReturn($selectMock); + $adapterMock->method('fetchPairs') + ->with($selectMock) + ->willReturn($this->swatchAttributesCodes); + + $this->resourceConnection + ->method('getConnection') + ->willReturn($adapterMock); + + $this->resourceConnection + ->method('getTableName') + ->withConsecutive( + [self::ATTRIBUTE_TABLE], + [self::ATTRIBUTE_OPTION_TABLE], + [self::SWATCH_OPTION_TABLE] + )->will(self::onConsecutiveCalls( + self::ATTRIBUTE_TABLE, + self::ATTRIBUTE_OPTION_TABLE, + self::SWATCH_OPTION_TABLE + )); + + $result = $this->swatchAttributeCodesModel->getCodes(); + $this->assertEquals($expected, $result); + } + + public function dataForGettingCodes() + { + return [ + [false, $this->swatchAttributesCodes], + [json_encode($this->swatchAttributesCodes), $this->swatchAttributesCodes] + ]; + } +} diff --git a/app/code/Magento/Swatches/Test/Unit/Model/SwatchAttributesProviderTest.php b/app/code/Magento/Swatches/Test/Unit/Model/SwatchAttributesProviderTest.php new file mode 100644 index 0000000000000..6dd0bf6f8e05e --- /dev/null +++ b/app/code/Magento/Swatches/Test/Unit/Model/SwatchAttributesProviderTest.php @@ -0,0 +1,114 @@ +typeConfigurableMock = $this->getMock( + Configurable::class, + ['getConfigurableAttributes', 'getCodes'], + [], + '', + false + ); + + $this->swatchAttributeCodesMock = $this->getMock( + SwatchAttributeCodes::class, + [], + [], + '', + false + ); + + $this->productMock = $this->getMock( + \Magento\Catalog\Model\Product::class, + ['getId', 'getTypeId'], + [], + '', + false + ); + + $this->swatchAttributeProvider = new SwatchAttributesProvider( + $this->typeConfigurableMock, + $this->swatchAttributeCodesMock + ); + } + + public function testProvide() + { + $this->productMock->method('getId')->willReturn(1); + $this->productMock->method('getTypeId') + ->willReturn(Configurable::TYPE_CODE); + + $productAttributeMock = $this->getMock( + Interceptor::class, + [], + [], + '', + false + ); + + $configAttributeMock = $this->getMock( + Configurable\Attribute::class, + ['getAttributeId', 'getProductAttribute'], + [], + '', + false + ); + $configAttributeMock + ->method('getAttributeId') + ->willReturn(1); + + $configAttributeMock + ->method('getProductAttribute') + ->willReturn($productAttributeMock); + + $this->typeConfigurableMock + ->method('getConfigurableAttributes') + ->with($this->productMock) + ->willReturn([$configAttributeMock]); + + $swatchAttributes = [1 => 'text_swatch']; + + $this->swatchAttributeCodesMock + ->method('getCodes') + ->willReturn($swatchAttributes); + + $expected = [1 => $productAttributeMock]; + + $result = $this->swatchAttributeProvider->provide($this->productMock); + + $this->assertEquals($expected, $result); + } +} diff --git a/app/code/Magento/Swatches/Test/Unit/Observer/AddFieldsToAttributeObserverTest.php b/app/code/Magento/Swatches/Test/Unit/Observer/AddFieldsToAttributeObserverTest.php index ddcd3b260ed72..03ca38f360134 100644 --- a/app/code/Magento/Swatches/Test/Unit/Observer/AddFieldsToAttributeObserverTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Observer/AddFieldsToAttributeObserverTest.php @@ -1,6 +1,6 @@ @@ -27,4 +27,12 @@ + + + + optiontext + optionvisual + + + diff --git a/app/code/Magento/Swatches/etc/adminhtml/events.xml b/app/code/Magento/Swatches/etc/adminhtml/events.xml index 16f053bd13f64..74e8dfa27965b 100644 --- a/app/code/Magento/Swatches/etc/adminhtml/events.xml +++ b/app/code/Magento/Swatches/etc/adminhtml/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/etc/adminhtml/routes.xml b/app/code/Magento/Swatches/etc/adminhtml/routes.xml index 2016bd77ed53b..a5f95cdb0556a 100644 --- a/app/code/Magento/Swatches/etc/adminhtml/routes.xml +++ b/app/code/Magento/Swatches/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/etc/adminhtml/system.xml b/app/code/Magento/Swatches/etc/adminhtml/system.xml index e41eaab6e0d0c..c16464e24dadb 100644 --- a/app/code/Magento/Swatches/etc/adminhtml/system.xml +++ b/app/code/Magento/Swatches/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,10 @@ + + + Magento\Config\Model\Config\Source\Yesno + diff --git a/app/code/Magento/Swatches/etc/config.xml b/app/code/Magento/Swatches/etc/config.xml index 7a968c2ff9493..54ef5ea728862 100644 --- a/app/code/Magento/Swatches/etc/config.xml +++ b/app/code/Magento/Swatches/etc/config.xml @@ -1,7 +1,7 @@ @@ -10,6 +10,7 @@ 16 + 1 diff --git a/app/code/Magento/Swatches/etc/di.xml b/app/code/Magento/Swatches/etc/di.xml index 525456d1f9eb6..114054ed28757 100644 --- a/app/code/Magento/Swatches/etc/di.xml +++ b/app/code/Magento/Swatches/etc/di.xml @@ -1,7 +1,7 @@ @@ -73,4 +73,12 @@
    + + + swatch-attribute-list + + Magento\Eav\Model\Entity\Attribute::CACHE_TAG + + + diff --git a/app/code/Magento/Swatches/etc/frontend/routes.xml b/app/code/Magento/Swatches/etc/frontend/routes.xml index f4d626cd64a73..aa2e6c9811e21 100644 --- a/app/code/Magento/Swatches/etc/frontend/routes.xml +++ b/app/code/Magento/Swatches/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Swatches/etc/module.xml b/app/code/Magento/Swatches/etc/module.xml index 9a54feefc80c4..7064539eb4553 100644 --- a/app/code/Magento/Swatches/etc/module.xml +++ b/app/code/Magento/Swatches/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/etc/view.xml b/app/code/Magento/Swatches/etc/view.xml index a4589ad7a892a..7533718b9196e 100644 --- a/app/code/Magento/Swatches/etc/view.xml +++ b/app/code/Magento/Swatches/etc/view.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/i18n/en_US.csv b/app/code/Magento/Swatches/i18n/en_US.csv index d000032ee429a..4ea18ba81355b 100644 --- a/app/code/Magento/Swatches/i18n/en_US.csv +++ b/app/code/Magento/Swatches/i18n/en_US.csv @@ -33,3 +33,4 @@ Image,Image "Image Size","Image Size" "Example format: 200x300.","Example format: 200x300." "Image Position","Image Position" +"The value of Admin must be unique.","The value of Admin must be unique." diff --git a/app/code/Magento/Swatches/registration.php b/app/code/Magento/Swatches/registration.php index fea11fdda25ec..024952430beb7 100644 --- a/app/code/Magento/Swatches/registration.php +++ b/app/code/Magento/Swatches/registration.php @@ -1,6 +1,6 @@ @@ -21,4 +21,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml b/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml index 3e420e0818af1..f9ffab2fa5ce6 100755 --- a/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml +++ b/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_attribute_edit_popup.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_form.xml b/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_form.xml index 76405c547344c..50431ad7c047f 100644 --- a/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_form.xml +++ b/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_superconfig_config.xml b/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_superconfig_config.xml index 59f50792575ff..575fee5707d12 100644 --- a/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_superconfig_config.xml +++ b/app/code/Magento/Swatches/view/adminhtml/layout/catalog_product_superconfig_config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/view/adminhtml/requirejs-config.js b/app/code/Magento/Swatches/view/adminhtml/requirejs-config.js index 32675d81ae1bd..903c90b8bd3cb 100644 --- a/app/code/Magento/Swatches/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/Swatches/view/adminhtml/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml index 8dc4f5cf21d41..ede7db9006849 100644 --- a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml +++ b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/js.phtml @@ -1,6 +1,6 @@ getStoresSortedBySortOrder(); ?>
    - + + escapeHtml(__('Manage Swatch (Values of Your Attribute)')) ?> +
    - + getId() != \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> - + - getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> class="_required"> - getName() ?> + @@ -35,14 +42,16 @@ $stores = $block->getStoresSortedBySortOrder(); - @@ -55,30 +64,56 @@ $stores = $block->getStoresSortedBySortOrder(); getId() != \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> @@ -87,7 +122,11 @@ $stores = $block->getStoresSortedBySortOrder(); diff --git a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml index dd6f4b26ecf12..2f398a540e672 100644 --- a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml +++ b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml @@ -1,6 +1,6 @@ getStoresSortedBySortOrder(); ?>
    - + + escapeHtml(__('Manage Swatch (Values of Your Attribute)')) ?>
    escapeHtml(__('Is Default')) ?> + escapeHtml(__('Swatch')); ?> + getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> + class="_required" + > + escapeHtml($_store->getName()) ?>
    +
    + getReadOnly() && !$block->canManageOptionDefaultOnly()):?> -
    getReadOnly() && !$block->canManageOptionDefaultOnly()): ?> -
    +
    - getReadOnly() || $block->canManageOptionDefaultOnly()): ?> disabled="disabled"/> + getReadOnly() || $block->canManageOptionDefaultOnly()): ?> + disabled="disabled" + />
    - getReadOnly()):?>disabled="disabled"/> + getReadOnly()):?>disabled="disabled"/> - + - getReadOnly() || $block->canManageOptionDefaultOnly()):?> disabled="disabled"/> + getReadOnly() || $block->canManageOptionDefaultOnly()):?> + disabled="disabled" + /> getReadOnly() && !$block->canManageOptionDefaultOnly()):?> -
    - - + + - getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> class="_required"> - getName() ?> + getStoresSortedBySortOrder(); - @@ -54,47 +61,71 @@ $stores = $block->getStoresSortedBySortOrder(); @@ -103,7 +134,11 @@ $stores = $block->getStoresSortedBySortOrder(); diff --git a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml index ad17bc1cb5c5d..0f9b16f95c674 100644 --- a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml +++ b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml @@ -1,6 +1,6 @@ @@ -48,12 +48,13 @@ + Magento_Catalog/component/image-size-field Image Size text input watermark_swatch_image_size - true + true Example format: 200x300. diff --git a/app/code/Magento/Swatches/view/adminhtml/ui_component/product_attribute_add_form.xml b/app/code/Magento/Swatches/view/adminhtml/ui_component/product_attribute_add_form.xml index d976296315566..54de75697a85d 100644 --- a/app/code/Magento/Swatches/view/adminhtml/ui_component/product_attribute_add_form.xml +++ b/app/code/Magento/Swatches/view/adminhtml/ui_component/product_attribute_add_form.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css b/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css index f52668f65f4dc..5bdb5d1b65428 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css +++ b/app/code/Magento/Swatches/view/adminhtml/web/css/swatches.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/form/element/swatch-visual.js b/app/code/Magento/Swatches/view/adminhtml/web/js/form/element/swatch-visual.js index 165a8cf8e1eda..bda847bf837a4 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/form/element/swatch-visual.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/form/element/swatch-visual.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js index 17f52b5d5f68f..4ea9bc01f89ae 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/text.js b/app/code/Magento/Swatches/view/adminhtml/web/js/text.js index ac7d7ab642c6e..eb0618701350e 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/text.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/text.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/type-change.js b/app/code/Magento/Swatches/view/adminhtml/web/js/type-change.js index c2f95f85b311d..d38ef5f87163d 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/type-change.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/type-change.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ require([ diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js b/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js index e8291d810d567..e769989497baf 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Swatches/view/adminhtml/web/template/swatch-visual.html b/app/code/Magento/Swatches/view/adminhtml/web/template/swatch-visual.html index fc20cfd77ca01..6351283b4bcce 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/template/swatch-visual.html +++ b/app/code/Magento/Swatches/view/adminhtml/web/template/swatch-visual.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Swatches/view/frontend/layout/catalog_category_view.xml b/app/code/Magento/Swatches/view/frontend/layout/catalog_category_view.xml index 3b17bac8e1540..501866f18b5d5 100644 --- a/app/code/Magento/Swatches/view/frontend/layout/catalog_category_view.xml +++ b/app/code/Magento/Swatches/view/frontend/layout/catalog_category_view.xml @@ -1,7 +1,7 @@ @@ -11,7 +11,7 @@ - + diff --git a/app/code/Magento/Swatches/view/frontend/layout/catalog_product_view_type_configurable.xml b/app/code/Magento/Swatches/view/frontend/layout/catalog_product_view_type_configurable.xml index 6ba9c47382f75..c5f6df9eb11f0 100755 --- a/app/code/Magento/Swatches/view/frontend/layout/catalog_product_view_type_configurable.xml +++ b/app/code/Magento/Swatches/view/frontend/layout/catalog_product_view_type_configurable.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/view/frontend/layout/catalogsearch_advanced_result.xml b/app/code/Magento/Swatches/view/frontend/layout/catalogsearch_advanced_result.xml new file mode 100644 index 0000000000000..501866f18b5d5 --- /dev/null +++ b/app/code/Magento/Swatches/view/frontend/layout/catalogsearch_advanced_result.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/app/code/Magento/Swatches/view/frontend/layout/catalogsearch_result_index.xml b/app/code/Magento/Swatches/view/frontend/layout/catalogsearch_result_index.xml index e8f01a8db45fd..98e9c54b4a793 100644 --- a/app/code/Magento/Swatches/view/frontend/layout/catalogsearch_result_index.xml +++ b/app/code/Magento/Swatches/view/frontend/layout/catalogsearch_result_index.xml @@ -1,7 +1,7 @@ @@ -9,4 +9,9 @@ + + + + + diff --git a/app/code/Magento/Swatches/view/frontend/layout/wishlist_index_configure_type_configurable.xml b/app/code/Magento/Swatches/view/frontend/layout/wishlist_index_configure_type_configurable.xml index 9b77cab3a1dcb..175d63bde3bc5 100644 --- a/app/code/Magento/Swatches/view/frontend/layout/wishlist_index_configure_type_configurable.xml +++ b/app/code/Magento/Swatches/view/frontend/layout/wishlist_index_configure_type_configurable.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml index 19b4002efb2a7..973ac0341734f 100644 --- a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml +++ b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/view/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/view/renderer.phtml index 19419d4c0a7ee..dbed0abbc8ff2 100644 --- a/app/code/Magento/Swatches/view/frontend/templates/product/view/renderer.phtml +++ b/app/code/Magento/Swatches/view/frontend/templates/product/view/renderer.phtml @@ -1,6 +1,6 @@ getJsonSwatchConfig(); ?>, "mediaCallback": "getMediaCallback() ?>", - "onlyMainImg": getVar('change_only_base_image', - 'Magento_Swatches') ?: 'false'; ?> + "gallerySwitchStrategy": "getVar('gallery_switch_strategy', + 'Magento_ConfigurableProduct') ?: 'replace'; ?>" } } } diff --git a/app/code/Magento/Swatches/view/frontend/web/css/swatches.css b/app/code/Magento/Swatches/view/frontend/web/css/swatches.css index 8204fc7fc8f63..15d419528dee3 100644 --- a/app/code/Magento/Swatches/view/frontend/web/css/swatches.css +++ b/app/code/Magento/Swatches/view/frontend/web/css/swatches.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js index dfd4b2bb2da0f..a52646d0d4e5e 100644 --- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -169,6 +169,9 @@ define([ //selector of product images gallery wrapper mediaGallerySelector: '[data-gallery-role=gallery-placeholder]', + // selector of category product tile wrapper + selectorProductTile: '.product-item', + // number of controls to show (false or zero = show all) numberToShow: false, @@ -190,8 +193,21 @@ define([ // Cache for BaseProduct images. Needed when option unset mediaGalleryInitial: [{}], - // - onlyMainImg: false + // whether swatches are rendered in product list or on product page + inProductList: false, + + /** + * Defines the mechanism of how images of a gallery should be + * updated when user switches between configurations of a product. + * + * As for now value of this option can be either 'replace' or 'prepend'. + * + * @type {String} + */ + gallerySwitchStrategy: 'replace', + + // sly-old-price block selector + slyOldPriceSelector: '.sly-old-price' }, /** @@ -236,17 +252,17 @@ define([ this.element.parents('.product-item-info'); if (isProductViewExist) { - gallery.on('gallery:loaded', function () { - var galleryObject = gallery.data('gallery'); - - options.mediaGalleryInitial = galleryObject.returnCurrentImages(); - }); + gallery.data('gallery') ? + this._onGalleryLoaded(gallery) : + gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery)); } else { options.mediaGalleryInitial = [{ 'img': $main.find('.product-image-photo').attr('src') }]; } - this.productForm = this.element.parents(this.options.selectorProduct).find('form:first'); + + this.productForm = this.element.parents(this.options.selectorProductTile).find('form:first'); + this.inProductList = this.productForm.length > 0; }, /** @@ -280,7 +296,7 @@ define([ ''; } - if ($widget.productForm) { + if ($widget.inProductList) { $widget.productForm.append(input); input = ''; } @@ -498,13 +514,16 @@ define([ * @private */ _OnClick: function ($this, $widget) { - var $parent = $this.parents('.' + $widget.options.classes.attributeClass), $label = $parent.find('.' + $widget.options.classes.attributeSelectedOptionLabelClass), attributeId = $parent.attr('attribute-id'), + $input = $parent.find('.' + $widget.options.classes.attributeInput); + + if ($widget.inProductList) { $input = $widget.productForm.find( '.' + $widget.options.classes.attributeInput + '[name="super_attribute[' + attributeId + ']"]' ); + } if ($this.hasClass('disabled')) { return; @@ -543,9 +562,13 @@ define([ _OnChange: function ($this, $widget) { var $parent = $this.parents('.' + $widget.options.classes.attributeClass), attributeId = $parent.attr('attribute-id'), + $input = $parent.find('.' + $widget.options.classes.attributeInput); + + if ($widget.inProductList) { $input = $widget.productForm.find( '.' + $widget.options.classes.attributeInput + '[name="super_attribute[' + attributeId + ']"]' ); + } if ($this.val() > 0) { $parent.attr('option-selected', $this.val()); @@ -688,6 +711,11 @@ define([ } ); + if (typeof result != 'undefined' && result.oldPrice.amount !== result.finalPrice.amount) { + $(this.options.slyOldPriceSelector).show(); + } else { + $(this.options.slyOldPriceSelector).hide(); + } }, /** @@ -900,26 +928,27 @@ define([ */ updateBaseImage: function (images, context, isProductViewExist) { var justAnImage = images[0], - updateImg, - imagesToUpdate, + initialImages = this.options.mediaGalleryInitial, gallery = context.find(this.options.mediaGallerySelector).data('gallery'), - item; + imagesToUpdate, + isInitial; if (isProductViewExist) { imagesToUpdate = images.length ? this._setImageType($.extend(true, [], images)) : []; + isInitial = _.isEqual(imagesToUpdate, initialImages); - if (this.options.onlyMainImg) { - updateImg = imagesToUpdate.filter(function (img) { - return img.isMain; - }); - item = updateImg.length ? updateImg[0] : imagesToUpdate[0]; - gallery.updateDataByIndex(0, item); + if (this.options.gallerySwitchStrategy === 'prepend' && !isInitial) { + imagesToUpdate = imagesToUpdate.concat(initialImages); + } - gallery.seek(1); - } else { - gallery.updateData(imagesToUpdate); + gallery.updateData(imagesToUpdate); + + if (isInitial) { $(this.options.mediaGallerySelector).AddFotoramaVideoEvents(); } + + gallery.first(); + } else if (justAnImage && justAnImage.img) { context.find('.product-image-photo').attr('src', justAnImage.img); } @@ -971,6 +1000,17 @@ define([ } return selectedAttributes; + }, + + /** + * Callback which fired after gallery gets initialized. + * + * @param {HTMLElement} element - DOM element associated with a gallery. + */ + _onGalleryLoaded: function (element) { + var galleryObject = element.data('gallery'); + + this.options.mediaGalleryInitial = galleryObject.returnCurrentImages(); } }); diff --git a/app/code/Magento/SwatchesLayeredNavigation/composer.json b/app/code/Magento/SwatchesLayeredNavigation/composer.json index 449677904c04b..11dd456885353 100644 --- a/app/code/Magento/SwatchesLayeredNavigation/composer.json +++ b/app/code/Magento/SwatchesLayeredNavigation/composer.json @@ -2,12 +2,12 @@ "name": "magento/module-swatches-layered-navigation", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/framework": "100.1.*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.2", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml b/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml index 1b91e7da1e5b6..403b13a54ed98 100644 --- a/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml +++ b/app/code/Magento/SwatchesLayeredNavigation/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/SwatchesLayeredNavigation/registration.php b/app/code/Magento/SwatchesLayeredNavigation/registration.php index 164603e6b531e..ea1540b617d26 100644 --- a/app/code/Magento/SwatchesLayeredNavigation/registration.php +++ b/app/code/Magento/SwatchesLayeredNavigation/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php b/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php index cbab5a59d34c7..1860097fec100 100644 --- a/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php +++ b/app/code/Magento/Tax/Api/Data/AppliedTaxInterface.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/etc/adminhtml/di.xml b/app/code/Magento/Tax/etc/adminhtml/di.xml index 120c6f9054e16..b14c61d5abbef 100644 --- a/app/code/Magento/Tax/etc/adminhtml/di.xml +++ b/app/code/Magento/Tax/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/adminhtml/menu.xml b/app/code/Magento/Tax/etc/adminhtml/menu.xml index 601f419cfef2e..624aef2e7fa05 100644 --- a/app/code/Magento/Tax/etc/adminhtml/menu.xml +++ b/app/code/Magento/Tax/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/adminhtml/routes.xml b/app/code/Magento/Tax/etc/adminhtml/routes.xml index 3e9c02010090a..531019d5f333d 100644 --- a/app/code/Magento/Tax/etc/adminhtml/routes.xml +++ b/app/code/Magento/Tax/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Tax/etc/adminhtml/system.xml b/app/code/Magento/Tax/etc/adminhtml/system.xml index 87b553dbba57a..5dedc5da96788 100644 --- a/app/code/Magento/Tax/etc/adminhtml/system.xml +++ b/app/code/Magento/Tax/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/catalog_attributes.xml b/app/code/Magento/Tax/etc/catalog_attributes.xml index 932edde556464..9628274563d2b 100644 --- a/app/code/Magento/Tax/etc/catalog_attributes.xml +++ b/app/code/Magento/Tax/etc/catalog_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/config.xml b/app/code/Magento/Tax/etc/config.xml index 0bf9428b7b582..2346b1e6b6d56 100644 --- a/app/code/Magento/Tax/etc/config.xml +++ b/app/code/Magento/Tax/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/crontab.xml b/app/code/Magento/Tax/etc/crontab.xml index ada862a7184b5..1060c426cb2e6 100644 --- a/app/code/Magento/Tax/etc/crontab.xml +++ b/app/code/Magento/Tax/etc/crontab.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/di.xml b/app/code/Magento/Tax/etc/di.xml index 09f969423f715..0435c871483d7 100644 --- a/app/code/Magento/Tax/etc/di.xml +++ b/app/code/Magento/Tax/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/events.xml b/app/code/Magento/Tax/etc/events.xml index 0fcfbdb2b9525..6d4a4ff94ae61 100644 --- a/app/code/Magento/Tax/etc/events.xml +++ b/app/code/Magento/Tax/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/extension_attributes.xml b/app/code/Magento/Tax/etc/extension_attributes.xml index 488da4b2efc48..61c5eefcd6268 100644 --- a/app/code/Magento/Tax/etc/extension_attributes.xml +++ b/app/code/Magento/Tax/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/fieldset.xml b/app/code/Magento/Tax/etc/fieldset.xml index 97495eb4fa842..37ec0cd6c577a 100644 --- a/app/code/Magento/Tax/etc/fieldset.xml +++ b/app/code/Magento/Tax/etc/fieldset.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/frontend/di.xml b/app/code/Magento/Tax/etc/frontend/di.xml index d7e3b6efe7283..a7b1c766c72f7 100644 --- a/app/code/Magento/Tax/etc/frontend/di.xml +++ b/app/code/Magento/Tax/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/frontend/events.xml b/app/code/Magento/Tax/etc/frontend/events.xml index ad8b2e1844145..206edaf93c7d2 100644 --- a/app/code/Magento/Tax/etc/frontend/events.xml +++ b/app/code/Magento/Tax/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/module.xml b/app/code/Magento/Tax/etc/module.xml index 3094aa2a11723..b816eec92ce0f 100644 --- a/app/code/Magento/Tax/etc/module.xml +++ b/app/code/Magento/Tax/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/pdf.xml b/app/code/Magento/Tax/etc/pdf.xml index 9deba5e82727b..a06265d4782d9 100644 --- a/app/code/Magento/Tax/etc/pdf.xml +++ b/app/code/Magento/Tax/etc/pdf.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/sales.xml b/app/code/Magento/Tax/etc/sales.xml index 8b283fa335729..3d437252cbd17 100644 --- a/app/code/Magento/Tax/etc/sales.xml +++ b/app/code/Magento/Tax/etc/sales.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/etc/webapi.xml b/app/code/Magento/Tax/etc/webapi.xml index 87dce6fc4e665..a67bc2dcb4123 100644 --- a/app/code/Magento/Tax/etc/webapi.xml +++ b/app/code/Magento/Tax/etc/webapi.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/registration.php b/app/code/Magento/Tax/registration.php index 7bf35ebbe6617..7e5d1ea05d9cb 100644 --- a/app/code/Magento/Tax/registration.php +++ b/app/code/Magento/Tax/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/sales_invoice_item_price.xml b/app/code/Magento/Tax/view/adminhtml/layout/sales_invoice_item_price.xml index fb62d5fd05d99..3d7663f8536fa 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/sales_invoice_item_price.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/sales_invoice_item_price.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/sales_order_create_item_price.xml b/app/code/Magento/Tax/view/adminhtml/layout/sales_order_create_item_price.xml index c69ccec0bb501..375b300e46892 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/sales_order_create_item_price.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/sales_order_create_item_price.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/sales_order_item_price.xml b/app/code/Magento/Tax/view/adminhtml/layout/sales_order_item_price.xml index 7d213aca53bf4..9d2fce3b7652f 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/sales_order_item_price.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/sales_order_item_price.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml index 4d33b0ad065bb..d900a7c957054 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportcsv.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportcsv.xml index 75aff061bb235..89c857f569f4c 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportcsv.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportcsv.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportxml.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportxml.xml index 75aff061bb235..89c857f569f4c 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportxml.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_exportxml.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_index.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_index.xml index cbf1a995756a6..270004a498ba1 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_index.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml index 72979563ac462..4a58a9894f43e 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_edit.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_edit.xml index 25e59aaf78701..0a9e6e3c59b3b 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_edit.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_index.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_index.xml index 56d94615ce868..83a60910ae318 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_index.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml b/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml index 92e57f57c8a9a..23bcbfbb4340e 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/class/page/edit.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/templates/items/price/row.phtml b/app/code/Magento/Tax/view/adminhtml/templates/items/price/row.phtml index 55c24a6417145..cba78caa5b2e6 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/items/price/row.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/items/price/row.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml index 1701323e53224..23068fd57de63 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/class/save.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml index 1dcc47c92436e..baa5f257ea7ac 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/toolbar/rule/save.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/base/templates/pricing/adjustment.phtml b/app/code/Magento/Tax/view/base/templates/pricing/adjustment.phtml index 20b8d0959f596..e3a765984d6ad 100644 --- a/app/code/Magento/Tax/view/base/templates/pricing/adjustment.phtml +++ b/app/code/Magento/Tax/view/base/templates/pricing/adjustment.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/layout/checkout_cart_sidebar_total_renderers.xml b/app/code/Magento/Tax/view/frontend/layout/checkout_cart_sidebar_total_renderers.xml index 0db666f4b60b8..93baddd73a9d3 100644 --- a/app/code/Magento/Tax/view/frontend/layout/checkout_cart_sidebar_total_renderers.xml +++ b/app/code/Magento/Tax/view/frontend/layout/checkout_cart_sidebar_total_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Tax/view/frontend/layout/checkout_index_index.xml index 03ba3dd94a8e0..f8eeca47a1376 100644 --- a/app/code/Magento/Tax/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Tax/view/frontend/layout/checkout_index_index.xml @@ -1,7 +1,7 @@ @@ -98,4 +98,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Tax/view/frontend/layout/checkout_item_price_renderers.xml b/app/code/Magento/Tax/view/frontend/layout/checkout_item_price_renderers.xml index ceb66a40b8f3e..5665eb0b5cd43 100644 --- a/app/code/Magento/Tax/view/frontend/layout/checkout_item_price_renderers.xml +++ b/app/code/Magento/Tax/view/frontend/layout/checkout_item_price_renderers.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/frontend/layout/sales_email_item_price.xml b/app/code/Magento/Tax/view/frontend/layout/sales_email_item_price.xml index 1788e2e60985a..0ef199db11b4d 100644 --- a/app/code/Magento/Tax/view/frontend/layout/sales_email_item_price.xml +++ b/app/code/Magento/Tax/view/frontend/layout/sales_email_item_price.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/frontend/layout/sales_order_item_price.xml b/app/code/Magento/Tax/view/frontend/layout/sales_order_item_price.xml index 36d47f7ccc590..acfb68b9c0de4 100644 --- a/app/code/Magento/Tax/view/frontend/layout/sales_order_item_price.xml +++ b/app/code/Magento/Tax/view/frontend/layout/sales_order_item_price.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Tax/view/frontend/templates/checkout/cart/item/price/sidebar.phtml b/app/code/Magento/Tax/view/frontend/templates/checkout/cart/item/price/sidebar.phtml index 814cebbc01548..9d1a1d40763da 100644 --- a/app/code/Magento/Tax/view/frontend/templates/checkout/cart/item/price/sidebar.phtml +++ b/app/code/Magento/Tax/view/frontend/templates/checkout/cart/item/price/sidebar.phtml @@ -1,6 +1,6 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Tax/view/frontend/templates/checkout/shipping/price.phtml b/app/code/Magento/Tax/view/frontend/templates/checkout/shipping/price.phtml index b40f55b07cf43..e289976f5981f 100644 --- a/app/code/Magento/Tax/view/frontend/templates/checkout/shipping/price.phtml +++ b/app/code/Magento/Tax/view/frontend/templates/checkout/shipping/price.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html index 42555380fbd25..afbe285629b24 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html index 162b86a395ff1..738a0125da02f 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html index 24d4bd41bbd0e..eb20767de779e 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html index 66ce615585d13..9b0077c3d4b11 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html index 059c79fbca120..0dd86baae2ebf 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html index d573308288e6c..60778bdba2117 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html @@ -1,6 +1,6 @@ @@ -31,4 +31,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html index f722bde43828b..ff4acc3ed5b49 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html index ddfbac7f3dd9c..9da9955d45f90 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html index 47c386892273b..68ccf75c6015d 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/TaxImportExport/Block/Adminhtml/Rate/Grid/Renderer/Country.php b/app/code/Magento/TaxImportExport/Block/Adminhtml/Rate/Grid/Renderer/Country.php index 8f79da385e618..da9b250e91149 100644 --- a/app/code/Magento/TaxImportExport/Block/Adminhtml/Rate/Grid/Renderer/Country.php +++ b/app/code/Magento/TaxImportExport/Block/Adminhtml/Rate/Grid/Renderer/Country.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/TaxImportExport/etc/adminhtml/menu.xml b/app/code/Magento/TaxImportExport/etc/adminhtml/menu.xml index 648752d188a8d..c6793683a4829 100644 --- a/app/code/Magento/TaxImportExport/etc/adminhtml/menu.xml +++ b/app/code/Magento/TaxImportExport/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/TaxImportExport/etc/adminhtml/routes.xml b/app/code/Magento/TaxImportExport/etc/adminhtml/routes.xml index 5485351813bec..566345bc2e90d 100644 --- a/app/code/Magento/TaxImportExport/etc/adminhtml/routes.xml +++ b/app/code/Magento/TaxImportExport/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/TaxImportExport/etc/module.xml b/app/code/Magento/TaxImportExport/etc/module.xml index a3128279232dd..931ebe9845a71 100644 --- a/app/code/Magento/TaxImportExport/etc/module.xml +++ b/app/code/Magento/TaxImportExport/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/TaxImportExport/registration.php b/app/code/Magento/TaxImportExport/registration.php index f00708bf0152f..c187a78c0d7b4 100644 --- a/app/code/Magento/TaxImportExport/registration.php +++ b/app/code/Magento/TaxImportExport/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/TaxImportExport/view/adminhtml/layout/tax_rule_edit.xml b/app/code/Magento/TaxImportExport/view/adminhtml/layout/tax_rule_edit.xml index c8f7e6f1fa87c..b8c36c9d4282c 100644 --- a/app/code/Magento/TaxImportExport/view/adminhtml/layout/tax_rule_edit.xml +++ b/app/code/Magento/TaxImportExport/view/adminhtml/layout/tax_rule_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/TaxImportExport/view/adminhtml/templates/importExport.phtml b/app/code/Magento/TaxImportExport/view/adminhtml/templates/importExport.phtml index e7ba46e851da5..12f48c00fda16 100644 --- a/app/code/Magento/TaxImportExport/view/adminhtml/templates/importExport.phtml +++ b/app/code/Magento/TaxImportExport/view/adminhtml/templates/importExport.phtml @@ -1,6 +1,6 @@ _storeManager->getStore()->isCurrentlySecure(), $this->_design->getDesignTheme()->getId(), $this->httpContext->getValue(Context::CONTEXT_AUTH), + $this->getTemplateFile(), + 'template' => $this->getTemplate() ]; } diff --git a/app/code/Magento/Theme/Block/Html/Header.php b/app/code/Magento/Theme/Block/Html/Header.php index 96f0f7976b42c..c6b9df82973e5 100644 --- a/app/code/Magento/Theme/Block/Html/Header.php +++ b/app/code/Magento/Theme/Block/Html/Header.php @@ -1,6 +1,6 @@ _mediaDirectory->getRelativePath($this->_appendScopeInfo(self::UPLOAD_DIR)); + return $this->_mediaDirectory->getRelativePath($this->_appendScopeInfo(static::UPLOAD_DIR)); } /** diff --git a/app/code/Magento/Theme/Model/Design/Backend/Theme.php b/app/code/Magento/Theme/Model/Design/Backend/Theme.php index c572495446556..039400434232f 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/Theme.php +++ b/app/code/Magento/Theme/Model/Design/Backend/Theme.php @@ -1,6 +1,6 @@ loadedData = $this->dataLoader->getData(); return $this->loadedData; } + + /** + * {@inheritdoc} + */ + public function getMeta() + { + $meta = parent::getMeta(); + if (!isset($meta['other_settings']['children'])) { + return $meta; + } + + $request = $this->getRequest()->getParams(); + if (!isset($request['scope'])) { + return $meta; + } + + $scope = $request['scope']; + $scopeCode = $this->getScopeCodeResolver()->resolve( + $scope, + isset($request['scope_id']) ? $request['scope_id'] : null + ); + + foreach ($meta['other_settings']['children'] as $settingGroupName => &$settingGroup) { + foreach ($settingGroup['children'] as $fieldName => &$field) { + $path = sprintf( + 'design/%s/%s', + $settingGroupName, + preg_replace('/^' . $settingGroupName . '_/', '', $fieldName) + ); + $isReadOnly = $this->getSettingChecker()->isReadOnly( + $path, + $scope, + $scopeCode + ); + + if ($isReadOnly) { + $field['arguments']['data']['config']['disabled'] = true; + $field['arguments']['data']['config']['is_disable_inheritance'] = true; + } + } + } + + return $meta; + } + + /** + * @deprecated + * @return ScopeCodeResolver + */ + private function getScopeCodeResolver() + { + if ($this->scopeCodeResolver === null) { + $this->scopeCodeResolver = ObjectManager::getInstance()->get(ScopeCodeResolver::class); + } + return $this->scopeCodeResolver; + } + + /** + * @deprecated + * @return SettingChecker + */ + private function getSettingChecker() + { + if ($this->settingChecker === null) { + $this->settingChecker = ObjectManager::getInstance()->get(SettingChecker::class); + } + return $this->settingChecker; + } + + /** + * @deprecated + * @return RequestInterface + */ + private function getRequest() + { + if ($this->request === null) { + $this->request = ObjectManager::getInstance()->get(RequestInterface::class); + } + return $this->request; + } } diff --git a/app/code/Magento/Theme/Model/Design/Config/DataProvider/DataLoader.php b/app/code/Magento/Theme/Model/Design/Config/DataProvider/DataLoader.php index d2362cd8735a1..461003b612e0f 100644 --- a/app/code/Magento/Theme/Model/Design/Config/DataProvider/DataLoader.php +++ b/app/code/Magento/Theme/Model/Design/Config/DataProvider/DataLoader.php @@ -1,6 +1,6 @@ themes[$fullPath])) { + return $this->themes[$fullPath]; + } + + if (! $this->getDeploymentConfig()->isDbAvailable()) { + return $this->getThemeList()->getThemeByFullPath($fullPath); + } + /** @var $themeCollection \Magento\Theme\Model\ResourceModel\Theme\Collection */ $theme = $this->cache->load('theme'. $fullPath); if ($theme) { - return unserialize($theme); + $this->themes[$fullPath] = unserialize($theme); + return $this->themes[$fullPath]; } $themeCollection = $this->collectionFactory->create(); $item = $themeCollection->getThemeByFullPath($fullPath); @@ -55,7 +86,9 @@ public function getThemeByFullPath($fullPath) $themeData = serialize($item); $this->cache->save($themeData, 'theme' . $fullPath); $this->cache->save($themeData, 'theme-by-id-' . $item->getId()); + $this->themes[$fullPath] = $item; } + return $item; } @@ -77,16 +110,45 @@ public function getThemeCustomizations( */ public function getThemeById($themeId) { + if (isset($this->themes[$themeId])) { + return $this->themes[$themeId]; + } $theme = $this->cache->load('theme-by-id-' . $themeId); if ($theme) { - return unserialize($theme); + $this->themes[$themeId] = unserialize($theme); + return $this->themes[$themeId]; } /** @var $themeModel \Magento\Framework\View\Design\ThemeInterface */ $themeModel = $this->themeFactory->create(); $themeModel->load($themeId); if ($themeModel->getId()) { $this->cache->save(serialize($themeModel), 'theme-by-id-' . $themeId); + $this->themes[$themeId] = $themeModel; } return $themeModel; } + + /** + * @deprecated + * @return ListInterface + */ + private function getThemeList() + { + if ($this->themeList === null) { + $this->themeList = ObjectManager::getInstance()->get(ListInterface::class); + } + return $this->themeList; + } + + /** + * @deprecated + * @return DeploymentConfig + */ + private function getDeploymentConfig() + { + if ($this->deploymentConfig === null) { + $this->deploymentConfig = ObjectManager::getInstance()->get(DeploymentConfig::class); + } + return $this->deploymentConfig; + } } diff --git a/app/code/Magento/Theme/Model/Theme/ThemeUninstaller.php b/app/code/Magento/Theme/Model/Theme/ThemeUninstaller.php index 4e450ef218c2e..33d14c030a2ed 100644 --- a/app/code/Magento/Theme/Model/Theme/ThemeUninstaller.php +++ b/app/code/Magento/Theme/Model/Theme/ThemeUninstaller.php @@ -1,6 +1,6 @@ objectManager = new ObjectManager($this); $this->dataLoader = $this->getMockBuilder('Magento\Theme\Model\Design\Config\DataProvider\DataLoader') ->disableOriginalConstructor() ->getMock(); @@ -57,6 +82,16 @@ protected function setUp() ->method('create') ->willReturn($this->collection); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->scopeCodeResolverMock = $this->getMockBuilder(ScopeCodeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $this->settingCheckerMock = $this->getMockBuilder(SettingChecker::class) + ->disableOriginalConstructor() + ->getMock(); + $this->model = new DataProvider( 'scope', 'scope', @@ -65,6 +100,21 @@ protected function setUp() $this->metadataLoader, $collectionFactory ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'request', + $this->requestMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'scopeCodeResolver', + $this->scopeCodeResolverMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'settingChecker', + $this->settingCheckerMock + ); } public function testGetData() @@ -79,4 +129,119 @@ public function testGetData() $this->assertEquals($data, $this->model->getData()); } + + /** + * @param array $inputMeta + * @param array $expectedMeta + * @param array $request + * @dataProvider getMetaDataProvider + */ + public function testGetMeta(array $inputMeta, array $expectedMeta, array $request) + { + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn($request); + $this->scopeCodeResolverMock->expects($this->any()) + ->method('resolve') + ->with('stores', 1) + ->willReturn('default'); + $this->settingCheckerMock->expects($this->any()) + ->method('isReadOnly') + ->withConsecutive( + ['design/head/welcome', 'stores', 'default'], + ['design/head/logo', 'stores', 'default'], + ['design/head/head', 'stores', 'default'] + ) + ->willReturnOnConsecutiveCalls( + true, + false, + true + ); + + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'meta', + $inputMeta + ); + + $this->assertSame($expectedMeta, $this->model->getMeta()); + } + + /** + * @return array + */ + public function getMetaDataProvider() + { + return [ + [ + [ + 'option1' + ], + [ + 'option1' + ], + [ + 'scope' => 'default' + ] + ], + [ + [ + 'other_settings' => [ + 'children' => [ + 'head' => [ + 'children' => [ + 'head_welcome' => [ + + ], + 'head_logo' => [ + + ], + 'head_head' => [ + + ] + ] + ] + ] + ] + ], + [ + 'other_settings' => [ + 'children' => [ + 'head' => [ + 'children' => [ + 'head_welcome' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true, + 'is_disable_inheritance' => true, + ] + ] + ] + ], + 'head_logo' => [ + + ], + 'head_head' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true, + 'is_disable_inheritance' => true, + ] + ] + ] + ] + ] + ] + ] + ] + ], + [ + 'scope' => 'stores', + 'scope_id' => 1 + ] + ] + ]; + } } diff --git a/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php index ceda9e18effa1..23a4c21ad5b4a 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/Test/Unit/Model/Layout/ConfigTest.php b/app/code/Magento/Theme/Test/Unit/Model/Layout/ConfigTest.php index e5c75c60d8e5c..0a23277a15655 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Layout/ConfigTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Layout/ConfigTest.php @@ -1,6 +1,6 @@ getMockBuilder(\Magento\Framework\App\DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + $deploymentConfig->expects($this->once()) + ->method('isDbAvailable') + ->willReturn(true); + + $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); + $objectManagerMock->expects($this->any()) + ->method('get') + ->willReturnMap([ + [\Magento\Framework\App\DeploymentConfig::class, $deploymentConfig], + ]); + \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); + $this->assertSame($theme, $themeProvider->getThemeByFullPath($path)); } @@ -66,6 +85,9 @@ public function testGetById() false ); $theme = $this->getMock('Magento\Theme\Model\Theme', [], [], '', false); + $theme->expects($this->once()) + ->method('getId') + ->willReturn(1); $theme->expects($this->once())->method('load')->with($themeId)->will($this->returnSelf()); $theme->expects($this->once())->method('getId')->will($this->returnValue(1)); $theme->expects($this->once())->method('__sleep')->will($this->returnValue([])); diff --git a/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeUninstallerTest.php b/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeUninstallerTest.php index 084559d286888..574917a8d7f1f 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeUninstallerTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeUninstallerTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/Test/Unit/Model/_files/frontend/magento_iphone/theme_invalid.xml b/app/code/Magento/Theme/Test/Unit/Model/_files/frontend/magento_iphone/theme_invalid.xml index cfe14f27cfec3..b88b6d7763d56 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/_files/frontend/magento_iphone/theme_invalid.xml +++ b/app/code/Magento/Theme/Test/Unit/Model/_files/frontend/magento_iphone/theme_invalid.xml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/Test/Unit/Observer/ApplyThemeCustomizationObserverTest.php b/app/code/Magento/Theme/Test/Unit/Observer/ApplyThemeCustomizationObserverTest.php index 38e04f5ead175..877cf7f19a921 100644 --- a/app/code/Magento/Theme/Test/Unit/Observer/ApplyThemeCustomizationObserverTest.php +++ b/app/code/Magento/Theme/Test/Unit/Observer/ApplyThemeCustomizationObserverTest.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/etc/adminhtml/di.xml b/app/code/Magento/Theme/etc/adminhtml/di.xml index 0c043c2e36bac..7d87e73be0b55 100644 --- a/app/code/Magento/Theme/etc/adminhtml/di.xml +++ b/app/code/Magento/Theme/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/adminhtml/menu.xml b/app/code/Magento/Theme/etc/adminhtml/menu.xml index d5b8401853a66..b93648178f48e 100644 --- a/app/code/Magento/Theme/etc/adminhtml/menu.xml +++ b/app/code/Magento/Theme/etc/adminhtml/menu.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/adminhtml/routes.xml b/app/code/Magento/Theme/etc/adminhtml/routes.xml index c94111cc1a420..d53a36e808b66 100644 --- a/app/code/Magento/Theme/etc/adminhtml/routes.xml +++ b/app/code/Magento/Theme/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/adminhtml/system.xml b/app/code/Magento/Theme/etc/adminhtml/system.xml index 84773112f504e..50bc4867f5aeb 100644 --- a/app/code/Magento/Theme/etc/adminhtml/system.xml +++ b/app/code/Magento/Theme/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/config.xml b/app/code/Magento/Theme/etc/config.xml index 5fa88578183d4..a383af866ce61 100644 --- a/app/code/Magento/Theme/etc/config.xml +++ b/app/code/Magento/Theme/etc/config.xml @@ -1,7 +1,7 @@ @@ -48,7 +48,7 @@ Disallow: /*SID= Default welcome msg!
    - Copyright © 2016 Magento. All rights reserved. + Copyright © 2017 Magento, Inc. All rights reserved.
    @@ -64,5 +64,10 @@ Disallow: /*SID= + + + 1 + + diff --git a/app/code/Magento/Theme/etc/di.xml b/app/code/Magento/Theme/etc/di.xml index 9cb17d93ab652..16ad235765652 100644 --- a/app/code/Magento/Theme/etc/di.xml +++ b/app/code/Magento/Theme/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/events.xml b/app/code/Magento/Theme/etc/events.xml index 94fd427a7a871..574f14709ab25 100644 --- a/app/code/Magento/Theme/etc/events.xml +++ b/app/code/Magento/Theme/etc/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/extension_attributes.xml b/app/code/Magento/Theme/etc/extension_attributes.xml index 54963d97a23cf..302392f78fc08 100644 --- a/app/code/Magento/Theme/etc/extension_attributes.xml +++ b/app/code/Magento/Theme/etc/extension_attributes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/frontend/di.xml b/app/code/Magento/Theme/etc/frontend/di.xml index 85086d694f378..3582aa9de3345 100644 --- a/app/code/Magento/Theme/etc/frontend/di.xml +++ b/app/code/Magento/Theme/etc/frontend/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/frontend/events.xml b/app/code/Magento/Theme/etc/frontend/events.xml index 1b744c83879df..97c3ecf930203 100644 --- a/app/code/Magento/Theme/etc/frontend/events.xml +++ b/app/code/Magento/Theme/etc/frontend/events.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/frontend/sections.xml b/app/code/Magento/Theme/etc/frontend/sections.xml index b6f899bfdc4cc..34ced88c82de4 100644 --- a/app/code/Magento/Theme/etc/frontend/sections.xml +++ b/app/code/Magento/Theme/etc/frontend/sections.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/indexer.xml b/app/code/Magento/Theme/etc/indexer.xml index 6b605fbae3758..002cca294181f 100644 --- a/app/code/Magento/Theme/etc/indexer.xml +++ b/app/code/Magento/Theme/etc/indexer.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/module.xml b/app/code/Magento/Theme/etc/module.xml index a30e3e1423e41..ae4f6955c6168 100644 --- a/app/code/Magento/Theme/etc/module.xml +++ b/app/code/Magento/Theme/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/etc/mview.xml b/app/code/Magento/Theme/etc/mview.xml index 36a94844a9504..24bc771909c89 100644 --- a/app/code/Magento/Theme/etc/mview.xml +++ b/app/code/Magento/Theme/etc/mview.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/i18n/en_US.csv b/app/code/Magento/Theme/i18n/en_US.csv index 3acb4616ea012..24b290c36fff1 100644 --- a/app/code/Magento/Theme/i18n/en_US.csv +++ b/app/code/Magento/Theme/i18n/en_US.csv @@ -135,7 +135,7 @@ Configuration,Configuration "This action will delete your custom instructions and reset robots.txt file to system's default settings.","This action will delete your custom instructions and reset robots.txt file to system's default settings." "Default Description","Default Description" "Default welcome msg!","Default welcome msg!" -"Copyright © 2016 Magento. All rights reserved.","Copyright © 2016 Magento. All rights reserved." +"Copyright © 2017 Magento, Inc. All rights reserved.","Copyright © 2017 Magento, Inc. All rights reserved." "Design Config Grid","Design Config Grid" "Rebuild design config grid index","Rebuild design config grid index" "Admin empty","Admin empty" diff --git a/app/code/Magento/Theme/registration.php b/app/code/Magento/Theme/registration.php index 6e72994a28264..58add46ee6909 100644 --- a/app/code/Magento/Theme/registration.php +++ b/app/code/Magento/Theme/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_edit.xml b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_edit.xml index 7886a1f61a639..5db690f54f186 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_edit.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_grid.xml b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_grid.xml index 1c44b080013f0..b3e4744acd8d2 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_grid.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_grid.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml index e844eb3344977..3e5166670ab36 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_contents.xml b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_contents.xml index 9017239e7c2e5..9ec72de7f5361 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_contents.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_contents.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_index.xml b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_index.xml index a19493b0587d6..b022ad86eab5b 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_index.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_wysiwyg_files_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_edit.xml b/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_edit.xml index 18cd928c15f8a..648ccc0c7a482 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_edit.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_edit.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_index.xml b/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_index.xml index 1a6391ecb6fcd..5a3b004bbfb7f 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_index.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/theme_design_config_index.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/layouts.xml b/app/code/Magento/Theme/view/adminhtml/layouts.xml index 552ddd7d72ec1..b8292d4b7db50 100644 --- a/app/code/Magento/Theme/view/adminhtml/layouts.xml +++ b/app/code/Magento/Theme/view/adminhtml/layouts.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml index 51684b30fac97..64def8572ff15 100644 --- a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml +++ b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-1column.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-2columns-left.xml b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-2columns-left.xml index 62dc716817221..b658e95a1cc4b 100644 --- a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-2columns-left.xml +++ b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-2columns-left.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-empty.xml b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-empty.xml index 2668639c5c26f..1ae61806dea7c 100644 --- a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-empty.xml +++ b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-empty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-login.xml b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-login.xml index c048ed9829d34..4beee7d41e5db 100644 --- a/app/code/Magento/Theme/view/adminhtml/page_layout/admin-login.xml +++ b/app/code/Magento/Theme/view/adminhtml/page_layout/admin-login.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/requirejs-config.js b/app/code/Magento/Theme/view/adminhtml/requirejs-config.js index bf72402dbf98c..a38a4991aa647 100644 --- a/app/code/Magento/Theme/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/Theme/view/adminhtml/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Theme/view/adminhtml/templates/browser/content.phtml b/app/code/Magento/Theme/view/adminhtml/templates/browser/content.phtml index 9fd6500f1e7f6..492655f3b6fa1 100644 --- a/app/code/Magento/Theme/view/adminhtml/templates/browser/content.phtml +++ b/app/code/Magento/Theme/view/adminhtml/templates/browser/content.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/templates/browser/content/files.phtml b/app/code/Magento/Theme/view/adminhtml/templates/browser/content/files.phtml index 4a7f0d77079d3..bae1e883150b9 100644 --- a/app/code/Magento/Theme/view/adminhtml/templates/browser/content/files.phtml +++ b/app/code/Magento/Theme/view/adminhtml/templates/browser/content/files.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/templates/tabs/fieldset/js.phtml b/app/code/Magento/Theme/view/adminhtml/templates/tabs/fieldset/js.phtml index a4d2088c559c9..8655e5b3a507f 100644 --- a/app/code/Magento/Theme/view/adminhtml/templates/tabs/fieldset/js.phtml +++ b/app/code/Magento/Theme/view/adminhtml/templates/tabs/fieldset/js.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/adminhtml/templates/title.phtml b/app/code/Magento/Theme/view/adminhtml/templates/title.phtml index aea940b2bda5c..3907203fde293 100644 --- a/app/code/Magento/Theme/view/adminhtml/templates/title.phtml +++ b/app/code/Magento/Theme/view/adminhtml/templates/title.phtml @@ -1,6 +1,6 @@ @@ -67,7 +67,7 @@ fileUploader Allowed file types: ico, png, gif, jpg, jpeg, apng, svg. Not all browsers support all these formats! 2097152 - jpg jpeg gif png svg + ico jpg jpeg gif png svg apng theme/design_config_fileUploader/save diff --git a/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_listing.xml b/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_listing.xml index 7f49d37e04cca..54db67209305b 100644 --- a/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_listing.xml +++ b/app/code/Magento/Theme/view/adminhtml/ui_component/design_config_listing.xml @@ -1,7 +1,7 @@ @@ -12,6 +12,7 @@ design_config_listing.design_config_listing_data_source design_config_columns + Magento_Config::config_design diff --git a/app/code/Magento/Theme/view/adminhtml/web/css/theme.css b/app/code/Magento/Theme/view/adminhtml/web/css/theme.css index eac172d38b5ba..508fdacf72659 100644 --- a/app/code/Magento/Theme/view/adminhtml/web/css/theme.css +++ b/app/code/Magento/Theme/view/adminhtml/web/css/theme.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Theme/view/adminhtml/web/js/bootstrap.js b/app/code/Magento/Theme/view/adminhtml/web/js/bootstrap.js index d3a48616a9b02..6c5ed9eaf54bf 100644 --- a/app/code/Magento/Theme/view/adminhtml/web/js/bootstrap.js +++ b/app/code/Magento/Theme/view/adminhtml/web/js/bootstrap.js @@ -1,10 +1,10 @@ /** * - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ require([ "jquery/fileUploader/jquery.fileupload-ui", "mage/adminhtml/browser", "Magento_Theme/js/form" -]); \ No newline at end of file +]); diff --git a/app/code/Magento/Theme/view/adminhtml/web/js/custom-js-list.js b/app/code/Magento/Theme/view/adminhtml/web/js/custom-js-list.js index 96d9bfeb3d687..cf15cadcc01f6 100644 --- a/app/code/Magento/Theme/view/adminhtml/web/js/custom-js-list.js +++ b/app/code/Magento/Theme/view/adminhtml/web/js/custom-js-list.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Theme/view/adminhtml/web/js/form.js b/app/code/Magento/Theme/view/adminhtml/web/js/form.js index e14a278242c6c..131ea2868aa24 100644 --- a/app/code/Magento/Theme/view/adminhtml/web/js/form.js +++ b/app/code/Magento/Theme/view/adminhtml/web/js/form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define(["prototype"], function(){ @@ -15,4 +15,4 @@ function parentThemeOnChange(selected, defaultsById) { window.parentThemeOnChange = parentThemeOnChange; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Theme/view/adminhtml/web/js/sortable.js b/app/code/Magento/Theme/view/adminhtml/web/js/sortable.js index 5c08661bb1324..830020e9a5908 100644 --- a/app/code/Magento/Theme/view/adminhtml/web/js/sortable.js +++ b/app/code/Magento/Theme/view/adminhtml/web/js/sortable.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -46,4 +46,4 @@ define([ }); return $.mage.sortable; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Theme/view/adminhtml/web/prototype/magento.css b/app/code/Magento/Theme/view/adminhtml/web/prototype/magento.css index 1f99c991d2228..e989db7091986 100644 --- a/app/code/Magento/Theme/view/adminhtml/web/prototype/magento.css +++ b/app/code/Magento/Theme/view/adminhtml/web/prototype/magento.css @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Theme/view/base/layouts.xml b/app/code/Magento/Theme/view/base/layouts.xml index 05598b5c83e43..c1489a2e66c47 100644 --- a/app/code/Magento/Theme/view/base/layouts.xml +++ b/app/code/Magento/Theme/view/base/layouts.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/base/page_layout/empty.xml b/app/code/Magento/Theme/view/base/page_layout/empty.xml index 82b36252e6f1a..395e629d04ad3 100644 --- a/app/code/Magento/Theme/view/base/page_layout/empty.xml +++ b/app/code/Magento/Theme/view/base/page_layout/empty.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/base/requirejs-config.js b/app/code/Magento/Theme/view/base/requirejs-config.js index abe587777dd9c..a9a077bf901d3 100644 --- a/app/code/Magento/Theme/view/base/requirejs-config.js +++ b/app/code/Magento/Theme/view/base/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Theme/view/base/templates/root.phtml b/app/code/Magento/Theme/view/base/templates/root.phtml index 5b8e62a03db01..ff5e67235e2fe 100644 --- a/app/code/Magento/Theme/view/base/templates/root.phtml +++ b/app/code/Magento/Theme/view/base/templates/root.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml index 25950342da680..fd2d6c6dbb2f1 100644 --- a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml +++ b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/layout/page_calendar.xml b/app/code/Magento/Theme/view/frontend/layout/page_calendar.xml index 353cb19f80da8..4093e646d48b6 100644 --- a/app/code/Magento/Theme/view/frontend/layout/page_calendar.xml +++ b/app/code/Magento/Theme/view/frontend/layout/page_calendar.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/layout/print.xml b/app/code/Magento/Theme/view/frontend/layout/print.xml index 9a4fe9578540d..37d599f301c93 100644 --- a/app/code/Magento/Theme/view/frontend/layout/print.xml +++ b/app/code/Magento/Theme/view/frontend/layout/print.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/layouts.xml b/app/code/Magento/Theme/view/frontend/layouts.xml index 143de45e9d43c..1b1a9c1956c51 100644 --- a/app/code/Magento/Theme/view/frontend/layouts.xml +++ b/app/code/Magento/Theme/view/frontend/layouts.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/page_layout/1column.xml b/app/code/Magento/Theme/view/frontend/page_layout/1column.xml index 268f14012d71a..0ce264465ca61 100644 --- a/app/code/Magento/Theme/view/frontend/page_layout/1column.xml +++ b/app/code/Magento/Theme/view/frontend/page_layout/1column.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/page_layout/2columns-left.xml b/app/code/Magento/Theme/view/frontend/page_layout/2columns-left.xml index 8c7994db8efaf..74fdf1dd176ed 100644 --- a/app/code/Magento/Theme/view/frontend/page_layout/2columns-left.xml +++ b/app/code/Magento/Theme/view/frontend/page_layout/2columns-left.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/page_layout/2columns-right.xml b/app/code/Magento/Theme/view/frontend/page_layout/2columns-right.xml index 3b6569068ac7a..62cda64a18d2c 100644 --- a/app/code/Magento/Theme/view/frontend/page_layout/2columns-right.xml +++ b/app/code/Magento/Theme/view/frontend/page_layout/2columns-right.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/page_layout/3columns.xml b/app/code/Magento/Theme/view/frontend/page_layout/3columns.xml index 3b6569068ac7a..62cda64a18d2c 100644 --- a/app/code/Magento/Theme/view/frontend/page_layout/3columns.xml +++ b/app/code/Magento/Theme/view/frontend/page_layout/3columns.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Theme/view/frontend/requirejs-config.js b/app/code/Magento/Theme/view/frontend/requirejs-config.js index 863a57e419387..4bd09ebd0ad2c 100644 --- a/app/code/Magento/Theme/view/frontend/requirejs-config.js +++ b/app/code/Magento/Theme/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Theme/view/frontend/templates/callouts/left_col.phtml b/app/code/Magento/Theme/view/frontend/templates/callouts/left_col.phtml index 20721c177ca17..5740c91b5b0c5 100644 --- a/app/code/Magento/Theme/view/frontend/templates/callouts/left_col.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/callouts/left_col.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/html/block.phtml b/app/code/Magento/Theme/view/frontend/templates/html/block.phtml index 89950dd77af5b..a9bffb4bbe269 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/block.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/block.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/html/collapsible.phtml b/app/code/Magento/Theme/view/frontend/templates/html/collapsible.phtml index 72ccd2e648e8d..32933e3a32747 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/collapsible.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/collapsible.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/html/footer.phtml b/app/code/Magento/Theme/view/frontend/templates/html/footer.phtml index 2a22184431ff4..d9de080002604 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/footer.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/footer.phtml @@ -1,6 +1,6 @@ -
    \ No newline at end of file +
    diff --git a/app/code/Magento/Theme/view/frontend/templates/html/notices.phtml b/app/code/Magento/Theme/view/frontend/templates/html/notices.phtml index 2d9c6877800d4..457da22298014 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/notices.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/notices.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/html/sections.phtml b/app/code/Magento/Theme/view/frontend/templates/html/sections.phtml index 04d211407db85..34deb16aa2b9b 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/sections.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/sections.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/js/components.phtml b/app/code/Magento/Theme/view/frontend/templates/js/components.phtml index e490a6aa04923..bdcb2e9bf7747 100644 --- a/app/code/Magento/Theme/view/frontend/templates/js/components.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/js/components.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/link.phtml b/app/code/Magento/Theme/view/frontend/templates/link.phtml index 42cdddf029931..c75589a8815ed 100644 --- a/app/code/Magento/Theme/view/frontend/templates/link.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/link.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml b/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml index 6866f6698c46b..d3bf6a342924d 100644 --- a/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Theme/view/frontend/templates/template.phtml b/app/code/Magento/Theme/view/frontend/templates/template.phtml index 0e7b5ee0a97dc..b836a0d1b8fa2 100644 --- a/app/code/Magento/Theme/view/frontend/templates/template.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/template.phtml @@ -1,6 +1,6 @@ source = $source; + } + + /** + * @inheritDoc + */ + public function get($path = '') + { + if (!$this->data) { + $this->data = new DataObject($this->source->get()); + } + + return $this->data->getData($path); + } + + /** + * Clean cache + * + * @return void + */ + public function clean() + { + $this->data = null; + } +} diff --git a/app/code/Magento/Translation/Block/Html/Head/Config.php b/app/code/Magento/Translation/Block/Html/Head/Config.php index 6a980bc815944..addb0ef5505e9 100644 --- a/app/code/Magento/Translation/Block/Html/Head/Config.php +++ b/app/code/Magento/Translation/Block/Html/Head/Config.php @@ -1,6 +1,6 @@ _translateInline->isAllowed()) { return ['inline' => 'not allowed']; } - $this->_appCache->invalidate(\Magento\Framework\App\Cache\Type\Translate::TYPE_IDENTIFIER); + + foreach ($this->cacheTypes as $cacheType) { + $this->_appCache->invalidate($cacheType); + } $this->_validateTranslationParams($translateParams); $this->_filterTranslationParams($translateParams, ['custom']); diff --git a/app/code/Magento/Translation/Model/Js/Config.php b/app/code/Magento/Translation/Model/Js/Config.php index 5ccfaccecf138..4e1618ce9e930 100644 --- a/app/code/Magento/Translation/Model/Js/Config.php +++ b/app/code/Magento/Translation/Model/Js/Config.php @@ -1,6 +1,6 @@ getStoreId(); } + $locale = (string) $locale; + $data = $this->getAppConfig()->get( + Translation::CONFIG_TYPE, + $locale . '/' . $this->getStoreCode($storeId), + [] + ); $connection = $this->getConnection(); - if (!$connection) { - return []; + if ($connection) { + $select = $connection->select() + ->from($this->getMainTable(), ['string', 'translate']) + ->where('store_id IN (0 , :store_id)') + ->where('locale = :locale') + ->order('store_id'); + $bind = [':locale' => $locale, ':store_id' => $storeId]; + $dbData = $connection->fetchPairs($select, $bind); + $data = array_replace($data, $dbData); } - - $select = $connection->select() - ->from($this->getMainTable(), ['string', 'translate']) - ->where('store_id IN (0 , :store_id)') - ->where('locale = :locale') - ->order('store_id'); - - $bind = [':locale' => (string)$locale, ':store_id' => $storeId]; - - return $connection->fetchPairs($select, $bind); + return $data; } /** @@ -115,6 +134,19 @@ public function getMainChecksum() return $this->getChecksum($this->getMainTable()); } + /** + * Get connection + * + * @return \Magento\Framework\DB\Adapter\AdapterInterface|false + */ + public function getConnection() + { + if (!$this->getDeployedConfig()->isDbAvailable()) { + return false; + } + return parent::getConnection(); + } + /** * Retrieve current store identifier * @@ -124,4 +156,39 @@ protected function getStoreId() { return $this->scopeResolver->getScope($this->scope)->getId(); } + + /** + * Retrieve store code by store id + * + * @param int $storeId + * @return string + */ + private function getStoreCode($storeId) + { + return $this->scopeResolver->getScope($storeId)->getCode(); + } + + /** + * @deprecated + * @return DeploymentConfig + */ + private function getDeployedConfig() + { + if ($this->deployedConfig === null) { + $this->deployedConfig = ObjectManager::getInstance()->get(DeploymentConfig::class); + } + return $this->deployedConfig; + } + + /** + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if ($this->appConfig === null) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } } diff --git a/app/code/Magento/Translation/Model/Source/InitialTranslationSource.php b/app/code/Magento/Translation/Model/Source/InitialTranslationSource.php new file mode 100644 index 0000000000000..8b89a89f02e20 --- /dev/null +++ b/app/code/Magento/Translation/Model/Source/InitialTranslationSource.php @@ -0,0 +1,82 @@ +translateFactory = $translateFactory; + $this->storeManager = $storeManager; + $this->deploymentConfig = $deploymentConfig; + } + + /** + * Read translations for the given 'path' from application initial configuration. + * + * @param string $path + * @return mixed + */ + public function get($path = '') + { + if (!$this->deploymentConfig->isDbAvailable()) { + return []; + } + + if (!$this->data) { + /** @var Translate $translate */ + $translate = $this->translateFactory->create(); + $select = $translate->getConnection()->select() + ->from($translate->getMainTable(), ['string', 'translate', 'store_id', 'locale']) + ->order('store_id'); + $translations = []; + foreach ($translate->getConnection()->fetchAll($select) as $item) { + $store = $this->storeManager->getStore($item['store_id']); + $translations[$item['locale']][$store->getCode()][$item['string']] = $item['translate']; + } + $this->data = new DataObject($translations); + } + return $this->data->getData($path) ?: []; + } +} diff --git a/app/code/Magento/Translation/Model/StringUtils.php b/app/code/Magento/Translation/Model/StringUtils.php index 508084aab55a9..4ff2b5b6aa930 100644 --- a/app/code/Magento/Translation/Model/StringUtils.php +++ b/app/code/Magento/Translation/Model/StringUtils.php @@ -1,6 +1,6 @@ source = $this->getMockBuilder(ConfigSourceInterface::class) + ->getMockForAbstractClass(); + $this->configType = new Translation($this->source); + } + + public function testGet() + { + $path = 'en_US/default'; + $data = [ + 'en_US' => [ + 'default' => [ + 'hello' => 'bonjour' + ] + ] + ]; + + $this->source->expects($this->once()) + ->method('get') + ->with() + ->willReturn($data); + + $this->assertEquals(['hello' => 'bonjour'], $this->configType->get($path)); + } +} diff --git a/app/code/Magento/Translation/Test/Unit/Block/JsTest.php b/app/code/Magento/Translation/Test/Unit/Block/JsTest.php index ed1c1bafd8173..b106bf92ee884 100644 --- a/app/code/Magento/Translation/Test/Unit/Block/JsTest.php +++ b/app/code/Magento/Translation/Test/Unit/Block/JsTest.php @@ -1,6 +1,6 @@ translationFactory = $this->getMockBuilder(TranslateFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->translation = $this->getMockBuilder(Translate::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager = $this->getMockBuilder(StoreManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->store = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->connection = $this->getMockBuilder(AdapterInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->select = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + $this->deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->source = new InitialTranslationSource( + $this->translationFactory, + $this->storeManager, + $this->deploymentConfigMock + ); + } + + public function testGet() + { + $this->deploymentConfigMock->expects($this->once()) + ->method('isDbAvailable') + ->willReturn(true); + $this->translationFactory->expects($this->once()) + ->method('create') + ->willReturn($this->translation); + $this->translation->expects($this->atLeastOnce()) + ->method('getConnection') + ->willReturn($this->connection); + $this->connection->expects($this->once()) + ->method('select') + ->willReturn($this->select); + $this->translation->expects($this->once()) + ->method('getMainTable') + ->willReturn('main_table.translate'); + $this->select->expects($this->once()) + ->method('from') + ->with('main_table.translate', ['string', 'translate', 'store_id', 'locale']) + ->willReturnSelf(); + $this->select->expects($this->once()) + ->method('order') + ->with('store_id') + ->willReturnSelf(); + $this->connection->expects($this->once()) + ->method('fetchAll') + ->with($this->select) + ->willReturn([ + [ + 'store_id' => 2, + 'locale' => 'en_US', + 'string' => 'hello', + 'translate' => 'bonjour' + ] + ]); + $this->storeManager->expects($this->once()) + ->method('getStore') + ->with(2) + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('getCode') + ->willReturn('myStore'); + + $this->assertEquals( + [ + 'en_US' => [ + 'myStore' => [ + 'hello' => 'bonjour' + ] + ] + ], + $this->source->get() + ); + } + + public function testGetWithoutAvailableDb() + { + $this->deploymentConfigMock->expects($this->once()) + ->method('isDbAvailable') + ->willReturn(false); + $this->assertEquals([], $this->source->get()); + } +} diff --git a/app/code/Magento/Translation/composer.json b/app/code/Magento/Translation/composer.json index 28b2fca992a8d..b18f86214a73d 100644 --- a/app/code/Magento/Translation/composer.json +++ b/app/code/Magento/Translation/composer.json @@ -2,15 +2,18 @@ "name": "magento/module-translation", "description": "N/A", "require": { - "php": "~5.6.0|7.0.2|~7.0.6", + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", "magento/module-backend": "100.1.*", "magento/module-developer": "100.1.*", "magento/module-store": "100.1.*", "magento/module-theme": "100.1.*", "magento/framework": "100.1.*" }, + "suggest": { + "magento/module-deploy": "100.1.*" + }, "type": "magento2-module", - "version": "100.1.0", + "version": "100.1.3", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Translation/etc/adminhtml/di.xml b/app/code/Magento/Translation/etc/adminhtml/di.xml index 564c1beedeb45..c66528d9b67e1 100644 --- a/app/code/Magento/Translation/etc/adminhtml/di.xml +++ b/app/code/Magento/Translation/etc/adminhtml/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Translation/etc/adminhtml/routes.xml b/app/code/Magento/Translation/etc/adminhtml/routes.xml index 06080c51733f5..96cbaa2d184b9 100644 --- a/app/code/Magento/Translation/etc/adminhtml/routes.xml +++ b/app/code/Magento/Translation/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Translation/etc/adminhtml/system.xml b/app/code/Magento/Translation/etc/adminhtml/system.xml index c60ff0db60100..7ce6719d92e01 100644 --- a/app/code/Magento/Translation/etc/adminhtml/system.xml +++ b/app/code/Magento/Translation/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Translation/etc/cache.xml b/app/code/Magento/Translation/etc/cache.xml index 00ad9577b5421..8e3f03dd503c5 100644 --- a/app/code/Magento/Translation/etc/cache.xml +++ b/app/code/Magento/Translation/etc/cache.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Translation/etc/config.xml b/app/code/Magento/Translation/etc/config.xml index 4ba907067cbfe..3c7fdbcead9cc 100644 --- a/app/code/Magento/Translation/etc/config.xml +++ b/app/code/Magento/Translation/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Translation/etc/di.xml b/app/code/Magento/Translation/etc/di.xml index c83ef46ea3080..05e4bc6d1bdb5 100644 --- a/app/code/Magento/Translation/etc/di.xml +++ b/app/code/Magento/Translation/etc/di.xml @@ -1,7 +1,7 @@ @@ -64,7 +64,6 @@
    - @@ -81,7 +80,6 @@ - @@ -89,4 +87,47 @@ + + + Magento\Framework\App\DeploymentConfig\Reader + Magento\Translation\App\Config\Type\Translation::CONFIG_TYPE + Magento\Framework\Config\File\ConfigFilePool::APP_CONFIG + + + + + + + Magento\Translation\Model\Source\InitialTranslationSource\Proxy + 100 + + + translationConfigInitialDataProvider + 1000 + + + + + + + translationConfigSourceAggregated + + + + + + Magento\Translation\App\Config\Type\Translation + + + + + + + + Magento\Translation\Model\Source\InitialTranslationSource + Magento\Translation\App\Config\Type\Translation::CONFIG_TYPE + + + + diff --git a/app/code/Magento/Translation/etc/frontend/routes.xml b/app/code/Magento/Translation/etc/frontend/routes.xml index d275b571e5f18..44eb6b5b7d68d 100644 --- a/app/code/Magento/Translation/etc/frontend/routes.xml +++ b/app/code/Magento/Translation/etc/frontend/routes.xml @@ -1,7 +1,7 @@ @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Translation/etc/module.xml b/app/code/Magento/Translation/etc/module.xml index e97d7ca3b3024..7abeb5bbdd49e 100644 --- a/app/code/Magento/Translation/etc/module.xml +++ b/app/code/Magento/Translation/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Translation/registration.php b/app/code/Magento/Translation/registration.php index cb7594cc431ef..d4118679a31be 100644 --- a/app/code/Magento/Translation/registration.php +++ b/app/code/Magento/Translation/registration.php @@ -1,6 +1,6 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Translation/view/base/web/js/i18n-config.js b/app/code/Magento/Translation/view/base/web/js/i18n-config.js index bc828f1dbe989..a880f615c609d 100644 --- a/app/code/Magento/Translation/view/base/web/js/i18n-config.js +++ b/app/code/Magento/Translation/view/base/web/js/i18n-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 'use strict'; diff --git a/app/code/Magento/Translation/view/frontend/requirejs-config.js b/app/code/Magento/Translation/view/frontend/requirejs-config.js index ad5c6fb3c4973..236bb0e504bdb 100644 --- a/app/code/Magento/Translation/view/frontend/requirejs-config.js +++ b/app/code/Magento/Translation/view/frontend/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml b/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml index 81e6ad796028e..13925354cb591 100644 --- a/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml +++ b/app/code/Magento/Translation/view/frontend/templates/translate_inline.phtml @@ -1,6 +1,6 @@ filterBuilder->setConditionType($type) ->setField($this->getName()) - ->setValue($value->format('Y-m-d H:i:s')) + ->setValue($value->format(static::$dateFormat)) ->create(); $this->getContext()->getDataProvider()->addFilter($filter); diff --git a/app/code/Magento/Ui/Component/Filters/Type/DateRange.php b/app/code/Magento/Ui/Component/Filters/Type/DateRange.php index 2ff6358ba7ffe..f07a76ac76677 100644 --- a/app/code/Magento/Ui/Component/Filters/Type/DateRange.php +++ b/app/code/Magento/Ui/Component/Filters/Type/DateRange.php @@ -1,6 +1,6 @@ factory->create($this->_request->getParam('namespace')); + + $aclResource = $component->getData('acl'); + + if ($aclResource && !$this->_authorization->isAllowed($aclResource)) { + $this->_redirect('admin/noroute'); + return; + } + $this->prepareComponent($component); $this->_response->appendBody((string) $component->render()); } diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Index/Render/Handle.php b/app/code/Magento/Ui/Controller/Adminhtml/Index/Render/Handle.php index 7a565ed2e28cb..defa8f8756045 100644 --- a/app/code/Magento/Ui/Controller/Adminhtml/Index/Render/Handle.php +++ b/app/code/Magento/Ui/Controller/Adminhtml/Index/Render/Handle.php @@ -1,6 +1,6 @@ requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http') @@ -40,20 +65,44 @@ protected function setUp() $this->responseMock = $this->getMockBuilder('Magento\Framework\App\Response\Http') ->disableOriginalConstructor() ->getMock(); - $contextMock = $this->getMockBuilder('Magento\Backend\App\Action\Context') + $this->contextMock = $this->getMockBuilder('Magento\Backend\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->uiFactoryMock = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->authorizationMock = $this->getMockBuilder(\Magento\Framework\AuthorizationInterface::class) + ->getMockForAbstractClass(); + $this->sessionMock = $this->getMockBuilder(\Magento\Backend\Model\Session::class) + ->disableOriginalConstructor() + ->getMock(); + $this->actionFlagMock = $this->getMockBuilder(\Magento\Framework\App\ActionFlag::class) + ->disableOriginalConstructor() + ->getMock(); + $this->helperMock = $this->getMockBuilder(\Magento\Backend\Helper\Data::class) ->disableOriginalConstructor() ->getMock(); - $contextMock->expects($this->any()) + + $this->contextMock->expects($this->any()) ->method('getRequest') ->willReturn($this->requestMock); - $contextMock->expects($this->any()) + $this->contextMock->expects($this->any()) ->method('getResponse') ->willReturn($this->responseMock); + $this->contextMock->expects($this->any()) + ->method('getAuthorization') + ->willReturn($this->authorizationMock); + $this->contextMock->expects($this->any()) + ->method('getSession') + ->willReturn($this->sessionMock); + $this->contextMock->expects($this->any()) + ->method('getActionFlag') + ->willReturn($this->actionFlagMock); + $this->contextMock->expects($this->any()) + ->method('getHelper') + ->willReturn($this->helperMock); - $this->uiFactoryMock = $this->getMockBuilder('Magento\Framework\View\Element\UiComponentFactory') - ->disableOriginalConstructor() - ->getMock(); - $this->render = new Render($contextMock, $this->uiFactoryMock); + $this->render = new Render($this->contextMock, $this->uiFactoryMock); } public function testExecuteAjaxRequest() @@ -96,4 +145,67 @@ public function testExecuteAjaxRequest() $this->render->executeAjaxRequest(); } + + /** + * @param string $acl + * @param bool $isAllowed + * @dataProvider executeAjaxRequestWithoutPermissionsDataProvider + */ + public function testExecuteAjaxRequestWithoutPermissions($acl, $isAllowed) + { + $name = 'test-name'; + $renderedData = 'data'; + + $this->requestMock->expects($this->any()) + ->method('getParam') + ->with('namespace') + ->willReturn($name); + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn([]); + $this->responseMock->expects($this->any()) + ->method('appendBody') + ->with($renderedData); + $this->authorizationMock->expects($acl ? $this->once() : $this->never()) + ->method('isAllowed') + ->with($acl) + ->willReturn($isAllowed); + + $componentMock = $this->getMockForAbstractClass( + \Magento\Framework\View\Element\UiComponentInterface::class, + [], + '', + false, + true, + true, + ['render'] + ); + $componentMock->expects($this->any()) + ->method('render') + ->willReturn($renderedData); + $componentMock->expects($this->any()) + ->method('getChildComponents') + ->willReturn([]); + $componentMock->expects($this->any()) + ->method('getData') + ->with('acl') + ->willReturn($acl); + $this->uiFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($componentMock); + + $this->render->executeAjaxRequest(); + } + + /** + * @return array + */ + public function executeAjaxRequestWithoutPermissionsDataProvider() + { + return [ + ['Magento_Test::index_index', true], + ['Magento_Test::index_index', false], + ['', null], + ]; + } } diff --git a/app/code/Magento/Ui/Test/Unit/DataProvider/EavValidationRulesTest.php b/app/code/Magento/Ui/Test/Unit/DataProvider/EavValidationRulesTest.php index ec5f8a49cedf6..dc661bfa1b602 100644 --- a/app/code/Magento/Ui/Test/Unit/DataProvider/EavValidationRulesTest.php +++ b/app/code/Magento/Ui/Test/Unit/DataProvider/EavValidationRulesTest.php @@ -1,6 +1,6 @@ @@ -45,4 +45,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/etc/adminhtml/routes.xml b/app/code/Magento/Ui/etc/adminhtml/routes.xml index 19da45aef65d5..9b5a5d97f06d7 100644 --- a/app/code/Magento/Ui/etc/adminhtml/routes.xml +++ b/app/code/Magento/Ui/etc/adminhtml/routes.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/adminhtml/system.xml b/app/code/Magento/Ui/etc/adminhtml/system.xml index 7df7570471b39..796304ff790fc 100644 --- a/app/code/Magento/Ui/etc/adminhtml/system.xml +++ b/app/code/Magento/Ui/etc/adminhtml/system.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/config.xml b/app/code/Magento/Ui/etc/config.xml index ddf2323431590..042d40eb5dcb5 100644 --- a/app/code/Magento/Ui/etc/config.xml +++ b/app/code/Magento/Ui/etc/config.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/data_source.xsd b/app/code/Magento/Ui/etc/data_source.xsd index c0bac03543f81..9d098f9998572 100644 --- a/app/code/Magento/Ui/etc/data_source.xsd +++ b/app/code/Magento/Ui/etc/data_source.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/di.xml b/app/code/Magento/Ui/etc/di.xml index 96525abe9f081..39a2935c67df1 100644 --- a/app/code/Magento/Ui/etc/di.xml +++ b/app/code/Magento/Ui/etc/di.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/module.xml b/app/code/Magento/Ui/etc/module.xml index 81585d7fd16c3..f9e1c5f041fbb 100644 --- a/app/code/Magento/Ui/etc/module.xml +++ b/app/code/Magento/Ui/etc/module.xml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/ui_components.xsd b/app/code/Magento/Ui/etc/ui_components.xsd index ace63b8a0b68c..aa84445ba1fb4 100644 --- a/app/code/Magento/Ui/etc/ui_components.xsd +++ b/app/code/Magento/Ui/etc/ui_components.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/ui_configuration.xsd b/app/code/Magento/Ui/etc/ui_configuration.xsd index e8c69d8e12d7c..adbe7e7cc8fd4 100644 --- a/app/code/Magento/Ui/etc/ui_configuration.xsd +++ b/app/code/Magento/Ui/etc/ui_configuration.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/ui_definition.xsd b/app/code/Magento/Ui/etc/ui_definition.xsd index c7160c7475bd4..f50bb6dfbe788 100644 --- a/app/code/Magento/Ui/etc/ui_definition.xsd +++ b/app/code/Magento/Ui/etc/ui_definition.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/etc/ui_template.xsd b/app/code/Magento/Ui/etc/ui_template.xsd index ed4c07d844585..e8e088ffa9115 100644 --- a/app/code/Magento/Ui/etc/ui_template.xsd +++ b/app/code/Magento/Ui/etc/ui_template.xsd @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/registration.php b/app/code/Magento/Ui/registration.php index 5c33ba05f074b..e7976c82547b0 100644 --- a/app/code/Magento/Ui/registration.php +++ b/app/code/Magento/Ui/registration.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/requirejs-config.js b/app/code/Magento/Ui/view/base/requirejs-config.js index ad2b75fd06f61..d0170d06c7697 100644 --- a/app/code/Magento/Ui/view/base/requirejs-config.js +++ b/app/code/Magento/Ui/view/base/requirejs-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/templates/container/content/default.phtml b/app/code/Magento/Ui/view/base/templates/container/content/default.phtml index 2a0cd37c68d37..1e805048885be 100644 --- a/app/code/Magento/Ui/view/base/templates/container/content/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/container/content/default.phtml @@ -1,5 +1,5 @@ diff --git a/app/code/Magento/Ui/view/base/templates/control/button/default.phtml b/app/code/Magento/Ui/view/base/templates/control/button/default.phtml index 7cb9db02b52c4..5fb56e2a35ffe 100644 --- a/app/code/Magento/Ui/view/base/templates/control/button/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/control/button/default.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/templates/layout/tabs/default.phtml b/app/code/Magento/Ui/view/base/templates/layout/tabs/default.phtml index bd25b7cc2823f..ca5a5a769da09 100644 --- a/app/code/Magento/Ui/view/base/templates/layout/tabs/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/layout/tabs/default.phtml @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/ui_component/templates/container/default.xhtml b/app/code/Magento/Ui/view/base/ui_component/templates/container/default.xhtml index d36d46312bfd6..a3088c81e1af5 100644 --- a/app/code/Magento/Ui/view/base/ui_component/templates/container/default.xhtml +++ b/app/code/Magento/Ui/view/base/ui_component/templates/container/default.xhtml @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/view/base/ui_component/templates/export/button.xhtml b/app/code/Magento/Ui/view/base/ui_component/templates/export/button.xhtml index c7410bd088f10..5045d6dbad8eb 100644 --- a/app/code/Magento/Ui/view/base/ui_component/templates/export/button.xhtml +++ b/app/code/Magento/Ui/view/base/ui_component/templates/export/button.xhtml @@ -1,7 +1,7 @@ @@ -9,4 +9,4 @@
    - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/ui_component/templates/form/collapsible.xhtml b/app/code/Magento/Ui/view/base/ui_component/templates/form/collapsible.xhtml index 4bc71f97da1d8..82cb73533286c 100644 --- a/app/code/Magento/Ui/view/base/ui_component/templates/form/collapsible.xhtml +++ b/app/code/Magento/Ui/view/base/ui_component/templates/form/collapsible.xhtml @@ -1,7 +1,7 @@ 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 index b9764d403f5cb..1029a55892da9 100644 --- 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 @@ -1,7 +1,7 @@ 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 index c515b356651ea..6b3feb43e27d7 100644 --- 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 @@ -1,7 +1,7 @@ diff --git a/app/code/Magento/Ui/view/base/web/js/block-loader.js b/app/code/Magento/Ui/view/base/web/js/block-loader.js index 0464c6f489ac7..419cbff22d214 100644 --- a/app/code/Magento/Ui/view/base/web/js/block-loader.js +++ b/app/code/Magento/Ui/view/base/web/js/block-loader.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 8c4539c14577b..d6b612dcde21b 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index 9dbd57b72341f..6f9bf5cc52859 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index e4fa285aaf440..2335a0bc4805e 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dnd.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dnd.js index d76fb433106ef..fefd4ba0fcf80 100644 --- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dnd.js +++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dnd.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -135,8 +135,8 @@ define([ drEl.instance = recordNode = this.processingStyles(recordNode, elem); drEl.instanceCtx = this.getRecord(originRecord[0]); drEl.eventMousedownY = isTouchDevice ? event.originalEvent.touches[0].pageY : event.pageY; - drEl.minYpos = $table.offset().top - originRecord.offset().top + $table.find('thead').outerHeight(); - drEl.maxYpos = drEl.minYpos + $table.find('tbody').outerHeight() - originRecord.outerHeight(); + drEl.minYpos = $table.offset().top - originRecord.offset().top + $table.children('thead').outerHeight(); + drEl.maxYpos = drEl.minYpos + $table.children('tbody').outerHeight() - originRecord.outerHeight(); $tableWrapper.append(recordNode); if (isTouchDevice) { diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js index bbc6033df0041..c0bd0156f5a0e 100644 --- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js +++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows-grid.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -23,6 +23,10 @@ define([ listens: { 'insertData': 'processingInsertData', 'recordData': 'initElements setToInsertData' + }, + mappingSettings: { + enabled: true, + distinct: true } }, @@ -100,10 +104,20 @@ define([ * @param {String|Number} recordId */ deleteRecord: function (index, recordId) { + this._super(); + + this.updateInsertData(recordId); + }, + + /** + * Updates insertData when record is deleted + * + * @param {String|Number} recordId + */ + updateInsertData: function (recordId) { var data = this.getElementData(this.insertData(), recordId), prop = this.map[this.identificationDRProperty]; - this._super(); this.insertData(_.reject(this.source.get(this.dataProvider), function (recordData) { return ~~recordData[prop] === ~~data[prop]; }, this)); @@ -163,7 +177,7 @@ define([ var changes = [], tmpObj = {}; - if (data.length !== this.relatedData) { + if (data.length !== this.relatedData.length) { data.forEach(function (obj) { tmpObj[this.identificationDRProperty] = obj[this.identificationDRProperty]; @@ -210,21 +224,27 @@ define([ var obj = {}, tmpObj = {}; - _.each(this.map, function (prop, index) { - obj[index] = !_.isUndefined(data[prop]) ? data[prop] : ''; - }, this); + if (this.mappingSettings.enabled) { + _.each(this.map, function (prop, index) { + obj[index] = !_.isUndefined(data[prop]) ? data[prop] : ''; + }, this); + } else { + obj = data; + } - tmpObj[this.identificationDRProperty] = obj[this.identificationDRProperty]; + if (this.mappingSettings.distinct) { + tmpObj[this.identificationDRProperty] = obj[this.identificationDRProperty]; + + if (_.findWhere(this.recordData(), tmpObj)) { + return false; + } + } if (!obj.hasOwnProperty(this.positionProvider)) { this.setMaxPosition(); obj[this.positionProvider] = this.maxPosition; } - if (_.findWhere(this.recordData(), tmpObj)) { - return false; - } - this.source.set(this.dataScope + '.' + this.index + '.' + this.recordData().length, obj); }, diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js index 37df101b208fb..f8af2229fc871 100644 --- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js +++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/record.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/record.js index 305de77d47dd8..8ea9bd1e58d52 100644 --- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/record.js +++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/record.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter.js b/app/code/Magento/Ui/view/base/web/js/form/adapter.js index 33cd1ba08deed..0e3c4ce60f4f4 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -84,4 +84,4 @@ define([ _.each(handlers, destroyListener); } }; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/button-adapter.js b/app/code/Magento/Ui/view/base/web/js/form/button-adapter.js index a074ee24dddde..4d602ec9c4c69 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/button-adapter.js +++ b/app/code/Magento/Ui/view/base/web/js/form/button-adapter.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 03cc557e87509..6b4c1a3262273 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 0185d3fbeeb64..b0547d30f3057 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/button.js b/app/code/Magento/Ui/view/base/web/js/form/components/button.js index 855b9ac5da177..e9889ce812ce4 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/button.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/button.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 9f7a74b481f2d..7fe3bb9b74599 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 7b8431143923d..7557c8801f486 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 c400fcac43a9a..5d0309d77883f 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -19,6 +19,9 @@ define([ level: 0, visible: true, disabled: false, + listens: { + 'opened': 'onVisibilityChange' + }, additionalClasses: {} }, @@ -30,7 +33,19 @@ define([ _.bindAll(this, 'onChildrenUpdate', 'onChildrenError', 'onContentLoading'); return this._super() - ._setClasses(); + ._setClasses(); + }, + + /** + * Initializes components' configuration. + * + * @returns {Fieldset} Chainable. + */ + initConfig: function () { + this._super(); + this._wasOpened = this.opened || !this.collapsible; + + return this; }, /** @@ -116,6 +131,17 @@ define([ return this; }, + /** + * Handler of the "opened" property changes. + * + * @param {Boolean} isOpened + */ + onVisibilityChange: function (isOpened) { + if (!this._wasOpened) { + this._wasOpened = isOpened; + } + }, + /** * Is being invoked on children validation error. * Sets error property to one incoming. 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 377261707dcf4..0ec4b88f8fc16 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 0daa67789e9d8..5bb96f8c78892 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/insert-form.js b/app/code/Magento/Ui/view/base/web/js/form/components/insert-form.js index f68e322a49dea..c6c0e3de4e47c 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/insert-form.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/insert-form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/insert-listing.js b/app/code/Magento/Ui/view/base/web/js/form/components/insert-listing.js index 2ed87501b743f..afca916df367f 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/insert-listing.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/insert-listing.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/insert.js b/app/code/Magento/Ui/view/base/web/js/form/components/insert.js index 0d3e9d99d39f9..6569266902b9b 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/insert.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/insert.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 81130caf18daa..0cd56d1b093e5 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 5d1af64a2b4ef..83be734666034 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 7c2bbc65cbd9b..122157b427dd7 100755 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 c426da9a1574c..813624b0928cb 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/checkbox-set.js b/app/code/Magento/Ui/view/base/web/js/form/element/checkbox-set.js index 3627d5d67752f..18f5722abe81b 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/checkbox-set.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/checkbox-set.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/country.js b/app/code/Magento/Ui/view/base/web/js/form/element/country.js new file mode 100644 index 0000000000000..4b857cc1ab18d --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/form/element/country.js @@ -0,0 +1,48 @@ +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + './select' +], function (_, registry, Select) { + 'use strict'; + + return Select.extend({ + defaults: { + imports: { + update: '${ $.parentName }.website_id:value' + } + }, + + /** + * Filters 'initialOptions' property by 'field' and 'value' passed, + * calls 'setOptions' passing the result to it + * + * @param {*} value + * @param {String} field + */ + filter: function (value, field) { + var result; + + if (!field) { //validate field, if we are on update + field = this.filterBy.field; + } + + this._super(value, field); + result = _.filter(this.initialOptions, function (item) { + + if (item[field]) { + return ~item[field].indexOf(value); + } + + return false; + }); + + this.setOptions(result); + } + }); +}); + diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js index 1805dcd2f004e..ce54a311b811f 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/media.js b/app/code/Magento/Ui/view/base/web/js/form/element/media.js index f8c27b55120cc..30b77626209f1 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/media.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/media.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 0a2d08b29f154..37b389dcba027 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 8edddba5ac807..66776725923e8 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/region.js b/app/code/Magento/Ui/view/base/web/js/form/element/region.js index 42a407262f53e..faac496251ac4 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/region.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/region.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -58,14 +58,16 @@ define([ var country = registry.get(this.parentName + '.' + 'country_id'), option = country.indexedOptions[value]; - this._super(value, field); + if (country) { + this._super(value, field); - if (option && option['is_region_visible'] === false) { - // hide select and corresponding text input field if region must not be shown for selected country - this.setVisible(false); + if (option && option['is_region_visible'] === false) { + // hide select and corresponding text input field if region must not be shown for selected country + this.setVisible(false); - if (this.customEntry) { - this.toggleInput(false); + if (this.customEntry) { + this.toggleInput(false); + } } } } 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 e28ec11fa8b34..23b663247ee1c 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -105,7 +105,9 @@ define([ return Abstract.extend({ defaults: { customName: '${ $.parentName }.${ $.index }_input', - elementTmpl: 'ui/form/element/select' + elementTmpl: 'ui/form/element/select', + caption: '', + options: [] }, /** @@ -127,28 +129,6 @@ define([ return this; }, - /** - * Parses options and merges the result with instance - * - * @param {Object} config - * @returns {Object} Chainable. - */ - initConfig: function (config) { - var options = config.options, - captionValue = config.captionValue || '', - result = parseOptions(options, captionValue); - - 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 @@ -160,7 +140,7 @@ define([ this.initialOptions = this.options; - this.observe('options') + this.observe('options caption') .setOptions(this.options()); return this; @@ -209,7 +189,7 @@ define([ return option && option.value; } - if (!this.caption) { + if (!this.caption()) { return findFirst(this.options); } }, @@ -254,14 +234,20 @@ define([ * @returns {Object} Chainable */ setOptions: function (data) { - var isVisible; + var captionValue = this.captionValue || '', + result = parseOptions(data, captionValue), + isVisible; + + this.indexedOptions = indexOptions(result.options); - this.indexedOptions = indexOptions(data); + this.options(result.options); - this.options(data); + if (!this.caption()) { + this.caption(result.caption); + } if (this.customEntry) { - isVisible = !!data.length; + isVisible = !!result.options.length; this.setVisible(isVisible); this.toggleInput(!isVisible); @@ -296,7 +282,7 @@ define([ * @returns {Object} Chainable. */ clear: function () { - var value = this.caption ? '' : findFirst(this.options); + var value = this.caption() ? '' : findFirst(this.options); this.value(value); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-toggle-notice.js b/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-toggle-notice.js index 1287a1e343891..bcad5c55080cb 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-toggle-notice.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-toggle-notice.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-use-config.js b/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-use-config.js index ad21484947049..b32d74ebeacb6 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-use-config.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox-use-config.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox.js b/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox.js index c303e5b09c716..5d4f6b48776d3 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/single-checkbox.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/text.js b/app/code/Magento/Ui/view/base/web/js/form/element/text.js index a30074431ff9a..779ed6b2fac83 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/text.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/text.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 36c3ae0b142b1..be4157c67d5d2 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js index 393b0f04e512c..37971d08a7b87 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -9,7 +9,8 @@ define([ 'Magento_Ui/js/lib/key-codes', 'mage/translate', 'ko', - 'jquery' + 'jquery', + 'Magento_Ui/js/lib/view/utils/async' ], function (_, Abstract, keyCodes, $t, ko, $) { 'use strict'; @@ -148,9 +149,14 @@ define([ showPath: true, labelsDecoration: false, disableLabel: false, + filterRateLimit: 500, closeBtnLabel: $t('Done'), optgroupTmpl: 'ui/grid/filters/elements/ui-select-optgroup', quantityPlaceholder: $t('options'), + hoverClass: '_hover', + rootListSelector: 'ul.admin__action-multiselect-menu-inner._root', + visibleOptionSelector: 'li.admin__action-multiselect-menu-inner-item:visible', + actionTargetSelector: '.action-menu-item', selectedPlaceholders: { defaultPlaceholder: $t('Select...'), lotPlaceholders: $t('Selected') @@ -179,6 +185,23 @@ define([ } }, + /** + * Initializes UISelect component. + * + * @returns {UISelect} Chainable. + */ + initialize: function () { + this._super(); + + $.async( + this.rootListSelector, + this, + this.onRootListRender.bind(this) + ); + + return this; + }, + /** * Parses options and merges the result with instance * Set defaults according to mode and levels configuration @@ -281,6 +304,8 @@ define([ 'filterOptionsFocus' ]); + this.filterInputValue.extend({rateLimit: this.filterRateLimit}); + return this; }, @@ -307,17 +332,22 @@ define([ * @returns {Boolean} level visibility. */ showLevels: function (data) { - var curLevel = ++data.level; + var curLevel = ++data.level, + isVisible; - if (!data.visible) { - data.visible = ko.observable(!!data.hasOwnProperty(this.separator) && + if (data.visible) { + isVisible = data.visible(); + } else { + isVisible = !!data.hasOwnProperty(this.separator) && _.isBoolean(this.levelsVisibility) && this.levelsVisibility || - data.hasOwnProperty(this.separator) && parseInt(this.levelsVisibility, 10) >= curLevel); + data.hasOwnProperty(this.separator) && parseInt(this.levelsVisibility, 10) >= curLevel; + data.visible = ko.observable(isVisible); + data.isVisited = isVisible; } - return data.visible(); + return isVisible; }, /** @@ -398,7 +428,13 @@ define([ var value = this.filterInputValue().trim().toLowerCase(), array = []; - if (value === '') { + if (value && value.length < 2) { + return false; + } + + this.cleanHoveredElement(); + + if (!value) { this.renderPath = false; this.options(this.cacheOptions.tree); this._setItemsQuantity(false); @@ -421,7 +457,6 @@ define([ this.options(array); this._setItemsQuantity(array.length); } - this.cleanHoveredElement(); return false; } @@ -509,8 +544,12 @@ define([ * @returns {Object} Chainable */ cleanHoveredElement: function () { - if (!_.isNull(this.hoverElIndex())) { - this.hoverElIndex(null); + if (this.hoveredElement) { + $(this.hoveredElement) + .children(this.actionTargetSelector) + .removeClass(this.hoverClass); + + this.hoveredElement = null; } return this; @@ -543,14 +582,16 @@ define([ * @return {Boolean} */ isHovered: function (data) { - var index = this.getOptionIndex(data), - status = this.hoverElIndex() === index; + var element = this.hoveredElement, + elementData; - if (this.selectType === 'optgroup' && data.hasOwnProperty(this.separator)) { + if (!element) { return false; } - return status; + elementData = ko.dataFor(this.hoveredElement); + + return data.value === elementData.value; }, /** @@ -612,10 +653,10 @@ define([ * Change visibility to child level * * @param {Object} data - element data - * @param {Object} elem - element */ - openChildLevel: function (data, elem) { - var contextElement; + openChildLevel: function (data) { + var contextElement = data, + isVisible; if ( this.openLevelsAction && @@ -623,8 +664,13 @@ define([ this.openLevelsAction && data.hasOwnProperty(this.separator) && parseInt(this.levelsVisibility, 10) <= data.level ) { - contextElement = ko.contextFor($(elem).parents('li').children('ul')[0]).$data.current; - contextElement.visible(!contextElement.visible()); + isVisible = !contextElement.visible(); + + if (isVisible && !contextElement.isVisited) { + contextElement.isVisited = true; + } + + contextElement.visible(isVisible); } }, @@ -642,25 +688,23 @@ define([ }, /** - * Add hover to some list element and clears element ID to variable + * @deprecated + */ + onMousemove: function () {}, + + /** + * Handles hover on list items. * - * @param {Object} data - object with data about this element - * @param {Number} index - element index * @param {Object} event - mousemove event */ - onMousemove: function (data, index, event) { - var id, - context = ko.contextFor(event.target); - - if (this.isCursorPositionChange(event)) { - return false; - } + onDelegatedMouseMouve: function (event) { + var target = $(event.currentTarget).closest(this.visibleOptionSelector)[0]; - if (typeof context.$data === 'object') { - id = this.getOptionIndex(context.$data); + if (this.isCursorPositionChange(event) || this.hoveredElement === target) { + return; } - id !== this.hoverElIndex() ? this.hoverElIndex(id) : false; + this._hoverTo(target); this.setCursorPosition(event); }, @@ -736,8 +780,8 @@ define([ } if (this.listVisible()) { - if (!_.isNull(this.hoverElIndex())) { - this.toggleOptionSelected(this.cacheOptions.plain[this.hoverElIndex()]); + if (this.hoveredElement) { + this.toggleOptionSelected(ko.dataFor(this.hoveredElement)); } } else { this.setListVisible(true); @@ -756,35 +800,7 @@ define([ * selected first option in list */ pageDownKeyHandler: function () { - var el, - nextEl, - nextData, - nextIndex; - - if (!this.listVisible()) { - return false; - } - - if (this.filterInputValue()) { - el = !_.isNull(this.hoverElIndex()) ? - this._getElemByData(this.cacheOptions.plain[this.hoverElIndex()]) : false; - nextEl = el ? el.next() : $(this.cacheUiSelect).find('li:visible').eq(0); - nextIndex = nextEl.length ? nextEl.index() : 0; - nextData = this.options()[nextIndex]; - this.hoverElIndex(this.getOptionIndex(nextData)); - - return false; - } - - if (!_.isNull(this.hoverElIndex()) && this.hoverElIndex() !== this.cacheOptions.plain.length - 1) { - this._setHoverToElement(1); - this._scrollTo(this.hoverElIndex()); - - return false; - } - - this._setHoverToElement(1, -1); - this._scrollTo(this.hoverElIndex()); + this._setHoverToElement(1); }, /** @@ -813,28 +829,19 @@ define([ * Set hover to visible element * * @param {Number} direction - iterator - * @param {Number} index - current hovered element - * @param {Array} list - collection items */ - _setHoverToElement: function (direction, index, list) { - var modifiedIndex, - curData, - canBeHovered = true; - - list = list || $(this.cacheUiSelect).find('li'); - index = index || _.isNumber(index) ? index : this.hoverElIndex(); - modifiedIndex = index + direction; - modifiedIndex < 0 ? modifiedIndex = this.cacheOptions.plain.length - 1 : false; - curData = this.cacheOptions.plain[modifiedIndex]; + _setHoverToElement: function (direction) { + var element; - if (this.selectType === 'optgroup' && !_.findWhere(this.cacheOptions.lastOptions, {value: curData.value})) { - canBeHovered = false; + if (direction === 1) { + element = this._getNextElement(); + } else if (direction === -1) { + element = this._getPreviousElement(); } - if (list.eq(modifiedIndex).is(':visible') && canBeHovered) { - this.hoverElIndex(modifiedIndex); - } else { - this._setHoverToElement(direction, modifiedIndex, list); + if (element) { + this._hoverTo(element); + this._scrollTo(element); } }, @@ -844,18 +851,15 @@ define([ * * @param {Number} index - element index */ - _scrollTo: function (index) { - var curEl, - parents, - wrapper, + _scrollTo: function (element) { + var curEl = $(element).children(this.actionTargetSelector), + wrapper = $(this.rootList), curElPos = {}, wrapperPos = {}; - curEl = $(this.cacheUiSelect).find('li').eq(index); - parents = curEl.parents('ul'); - wrapper = parents.eq(parents.length - 1); curElPos.start = curEl.offset().top; - curElPos.end = curElPos.start + curEl.height(); + curElPos.end = curElPos.start + curEl.outerHeight(); + wrapperPos.start = wrapper.offset().top; wrapperPos.end = wrapperPos.start + wrapper.height(); @@ -871,46 +875,7 @@ define([ * selected last option in list */ pageUpKeyHandler: function () { - var el, - nextEl, - nextIndex, - nextData; - - if (!this.listVisible()) { - return false; - } - - if (this.filterInputValue()) { - el = !_.isNull(this.hoverElIndex()) ? - this._getElemByData(this.cacheOptions.plain[this.hoverElIndex()]) : false; - nextEl = el ? el.prev() : $(this.cacheUiSelect).find('li:visible').eq(this.options().length-1); - nextIndex = nextEl.length ? nextEl.index() : this.options().length-1; - nextData = this.options()[nextIndex]; - this.hoverElIndex(this.getOptionIndex(nextData)); - - return false; - } - - - if (this.filterInputValue()) { - el = !_.isNull(this.hoverElIndex()) ? - this._getElemByData(this.cacheOptions.plain[this.hoverElIndex()]) : false; - nextEl = el ? el.next() : $(this.cacheUiSelect).find('li:visible').eq(0); - nextIndex = nextEl.length ? nextEl.index() : 0; - nextData = this.options()[nextIndex]; - this.hoverElIndex(this.getOptionIndex(nextData)); - - return false; - } - - if (this.hoverElIndex()) { - this._setHoverToElement(-1); - this._scrollTo(this.hoverElIndex()); - - return false; - } - this._setHoverToElement(-1, this.cacheOptions.plain.length); - this._scrollTo(this.hoverElIndex()); + this._setHoverToElement(-1); }, /** @@ -990,6 +955,129 @@ define([ return selected.map(function (option) { return option.label; }).join(', '); + }, + + /** + * Defines previous option element to + * the one that is currently hovered. + * + * @returns {Element} + */ + _getPreviousElement: function () { + var currentElement = this.hoveredElement, + lastElement = this._getLastIn(this.rootList), + previousElement; + + if (!currentElement) { + return lastElement; + } + + previousElement = $(currentElement).prev()[0]; + + return ( + this._getLastIn(previousElement) || + previousElement || + this._getFirstParentOf(currentElement) || + lastElement + ); + }, + + /** + * Defines next option element to + * the one that is currently hovered. + * + * @returns {Element} + */ + _getNextElement: function () { + var currentElement = this.hoveredElement, + firstElement = this._getFirstIn(this.rootList); + + if (!currentElement) { + return firstElement; + } + + return ( + this._getFirstIn(currentElement) || + $(currentElement).next()[0] || + this._getParentsOf(currentElement).next()[0] || + firstElement + ); + }, + + /** + * Returns first option element in provided scope. + * + * @param {Element} scope + * @returns {Element} + */ + _getFirstIn: function (scope) { + return $(scope).find(this.visibleOptionSelector)[0]; + }, + + /** + * Returns last descendant option element in provided scope. + * + * @param {Element} scope + * @returns {Element} + */ + _getLastIn: function (scope) { + return $(scope).find(this.visibleOptionSelector).last()[0]; + }, + + /** + * Returns a collection of parent option elements. + * + * @param {Element} scope + * @returns {jQueryCollection} + */ + _getParentsOf: function (scope) { + return $(scope).parents(this.visibleOptionSelector); + }, + + /** + * Returns first parent option element. + * + * @param {Element} scope + * @returns {Element} + */ + _getFirstParentOf: function (scope) { + return this._getParentsOf(scope)[0]; + }, + + /** + * Sets hover class to provided option element. + * + * @param {Element} element + */ + _hoverTo: function(element) { + if (this.hoveredElement) { + $(this.hoveredElement) + .children(this.actionTargetSelector) + .removeClass(this.hoverClass); + } + + $(element) + .children(this.actionTargetSelector) + .addClass(this.hoverClass); + + this.hoveredElement = element; + }, + + /** + * Callback which fires when root list element is rendered. + * + * @param {Element} element + */ + onRootListRender: function (element) { + var targetSelector = 'li > ' + this.actionTargetSelector; + + this.rootList = element; + + $(this.rootList).on( + 'mousemove', + targetSelector, + this.onDelegatedMouseMouve.bind(this) + ); } }); }); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/website.js b/app/code/Magento/Ui/view/base/web/js/form/element/website.js new file mode 100644 index 0000000000000..a5b08dadcf2e1 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/form/element/website.js @@ -0,0 +1,33 @@ +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'uiRegistry', + './select' +], function (_, registry, Select) { + 'use strict'; + + return Select.extend({ + defaults: { + customerId: null, + isGlobalScope: 0 + }, + + /** + * Website component constructor. + * @returns {exports} + */ + initialize: function () { + this._super(); + + if (this.customerId || this.isGlobalScope) { + this.disable(true); + } + + return this; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js index b3db5d11b98a5..1697d78a7f48c 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 index 60ffd0e69903b..1ef9e64393c37 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/form.js +++ b/app/code/Magento/Ui/view/base/web/js/form/form.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 ae6cb6aca371b..3e53979de381d 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index 82cb14f0f7b91..cd3a6bf9be78d 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 index 81aed578c1411..03f0c2a69ead5 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index 0b694bb94ca20..a7e33a739330b 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index dfc57613c9e95..8436ff81da1f5 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/onoff.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/onoff.js index b9670993f4a37..9f25cd47f8975 100755 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/onoff.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/onoff.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index c710ef606dcd0..a52996f8db742 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/thumbnail.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/thumbnail.js index 32247e03baa04..796572b83fcb9 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/thumbnail.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/thumbnail.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js b/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js index e0e5ca5c5e830..89e71b47f16dd 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/storage.js b/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/storage.js index a4280d72d6fd7..31cb26a97aa2c 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/storage.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/storage.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index 67fc893452cfc..6bb7a082e6e06 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js index d87b6b6b665ca..950e87b2bfb58 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -79,6 +79,10 @@ define([ getData: function (params, options) { var cachedRequest = this.getRequest(params); + if (params && params.filters && params.filters['store_id']) { + cachedRequest = false; + } + options = options || {}; return !options.refresh && cachedRequest ? diff --git a/app/code/Magento/Ui/view/base/web/js/grid/dnd.js b/app/code/Magento/Ui/view/base/web/js/grid/dnd.js index 1ebe9c1c099dc..314348619e140 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/dnd.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/dnd.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/editing/bulk.js b/app/code/Magento/Ui/view/base/web/js/grid/editing/bulk.js index b7a688fa1b4fe..59b4978555b89 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/editing/bulk.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/editing/bulk.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/editing/client.js b/app/code/Magento/Ui/view/base/web/js/grid/editing/client.js index 87bec175766d2..e38a8f1e9a169 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/editing/client.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/editing/client.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js b/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js index c2ed421c9276e..c6d03010bbec0 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/editing/editor.js b/app/code/Magento/Ui/view/base/web/js/grid/editing/editor.js index b39fb1a371801..0b201608b8e9c 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/editing/editor.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/editing/editor.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/editing/record.js b/app/code/Magento/Ui/view/base/web/js/grid/editing/record.js index cb81adc69d72c..1b33355981341 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/editing/record.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/editing/record.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/export.js b/app/code/Magento/Ui/view/base/web/js/grid/export.js index ce7fac2bdd477..6aae5b4ef9b01 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/export.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/export.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js index 75ec9452b192b..2a94e14d32da5 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index 0ce86c5fad84f..1fd73390cd228 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/range.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/range.js index b068af92aecf6..cb801192610de 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/filters/range.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/range.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index 2ab3794783e47..d1e00374e064e 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/listing.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/listing.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 index fda02be219b58..cd7e749914b0d 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js b/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js index c77b4b9560a61..8a01ff014d3aa 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js b/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js index a4c423e13849a..4998c89cc7271 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 index 92a4a6fd38cc5..8b5997f840884 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/provider.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/provider.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -43,6 +43,10 @@ define([ .initStorage() .clearData(); + // Load data when there will + // be no more pending assets. + resolver(this.reload, this); + return this; }, @@ -122,9 +126,11 @@ define([ * Handles changes of 'params' object. */ onParamsChange: function () { - this.firstLoad ? - resolver(this.reload, this) : + // It's necessary to make a reload only + // after the initial loading has been made. + if (!this.firstLoad) { this.reload(); + } }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/grid/resize.js b/app/code/Magento/Ui/view/base/web/js/grid/resize.js index bad2061ec7635..fe04d482d406e 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/resize.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/resize.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js index 5760866ec3376..01b2cdb713f43 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/search/search.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/search/search.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js b/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js index feea9a4359aa5..90f695da17980 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/toolbar.js b/app/code/Magento/Ui/view/base/web/js/grid/toolbar.js index 692176ab2a43a..036be579edcbb 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/toolbar.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/toolbar.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js index 57aacde2553c5..57e3a43245e56 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/collapsible.js b/app/code/Magento/Ui/view/base/web/js/lib/collapsible.js index 54ed9e8099817..9c18c97dbc4cb 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/collapsible.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/collapsible.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/class.js b/app/code/Magento/Ui/view/base/web/js/lib/core/class.js index 42458cc539e27..8cf4a6497254f 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/class.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/class.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js b/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js index 49133721369c8..abfb0c2545799 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -268,6 +268,14 @@ define([ _.each(grouped, this.updateRegion, this); + _.each(this.regions, function (items) { + var hasObsoleteComponents = items().length && !_.intersection(_elems, items()).length; + + if (hasObsoleteComponents) { + items.removeAll(); + } + }); + this.elems(_elems); return this; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/element/element.js b/app/code/Magento/Ui/view/base/web/js/lib/core/element/element.js index 0b2ce22c03c42..a4b9d478567c3 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/element/element.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/element/element.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js b/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js index 36fe39038a8a7..918a881cc6206 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/events.js b/app/code/Magento/Ui/view/base/web/js/lib/core/events.js index 10d0d788524e7..ac540ecf9250b 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/events.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/events.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js b/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js index f1b7097686a55..41dba4c928c6c 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/storage/local.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/key-codes.js b/app/code/Magento/Ui/view/base/web/js/lib/key-codes.js index caa03401632cd..e04c68118186b 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/key-codes.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/key-codes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/after-render.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/after-render.js index feac4919520f7..9f44678e53df5 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/after-render.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/after-render.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/autoselect.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/autoselect.js index 69cbcec3121d1..350c478ddee0d 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/autoselect.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/autoselect.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bind-html.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bind-html.js index 14474d240130d..f6d6a54554800 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bind-html.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bind-html.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js index 7948db67a269e..236dda8d68df1 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define(function (require) { diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/collapsible.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/collapsible.js index c14a39cd657a4..20afa10f00686 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/collapsible.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/collapsible.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js index 8f0fb7b007caf..1ef44a4031d6b 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** Creates datepicker binding and registers in to ko.bindingHandlers object */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/fadeVisible.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/fadeVisible.js index 2d728c7cdfd4c..819ae4694f3e8 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/fadeVisible.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/fadeVisible.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/i18n.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/i18n.js index d72a2eb44a7df..2d76217280c27 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/i18n.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/i18n.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/keyboard.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/keyboard.js index 55e092463bdb5..990d8c1a9a076 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/keyboard.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/keyboard.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/mage-init.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/mage-init.js index 1c39f5b76ddc2..f4dd857829cec 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/mage-init.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/mage-init.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js index aff207681c61c..daad48d4618b7 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -289,4 +289,4 @@ define([ } }; ko.bindingHandlers.selectedOptions.after.push('optgroup'); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/outer_click.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/outer_click.js index 43ecd7b73289f..cf2d2c8bcc932 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/outer_click.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/outer_click.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** Creates outerClick binding and registers in to ko.bindingHandlers object */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js index 6af75d555e127..f60882ad81f54 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/resizable.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/resizable.js index c83c0f6a79af0..cbafdec12066b 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/resizable.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/resizable.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/scope.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/scope.js index 24c45af372b5b..2a96198f8d157 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/scope.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/scope.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** Creates scope binding and registers in to ko.bindingHandlers object */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/simple-checked.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/simple-checked.js index 9b3a01fe90ef6..3ac920170c03f 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/simple-checked.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/simple-checked.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/staticChecked.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/staticChecked.js index 4237e50ca7e0b..51785d14013cd 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/staticChecked.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/staticChecked.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index 819058ff7a8dd..8505520b310f4 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js index 47cfc1135eb99..8ead6884dc570 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** Loads all available knockout bindings, sets custom template engine, initializes knockout on page */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js index 7b297a6a1ea14..2601486a8a649 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/bound-nodes.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/observable_array.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/observable_array.js index 3c3898234c7cb..a768de38b2048 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/observable_array.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/extender/observable_array.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/engine.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/engine.js index b612d4be5f02b..11cfe300cfbfc 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/engine.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/engine.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/loader.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/loader.js index b1d878c43db9e..5d5961f320442 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/loader.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/loader.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/observable_source.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/observable_source.js index b5c1af3c2eaac..f126a1abf6478 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/observable_source.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/observable_source.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js index c668dde7a17c2..f1c51be0087ba 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 034eae9c67b33..98261af055666 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ 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 905fb88852bbb..e98e7a51226b5 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/step-wizard.js b/app/code/Magento/Ui/view/base/web/js/lib/step-wizard.js index ad4d680771c07..f110af57de1f3 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/step-wizard.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/step-wizard.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ // jscs:disable jsDoc diff --git a/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js b/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js index 555c10ee04b70..4702120860285 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -49,13 +49,13 @@ define([ return _.mapObject({ "min_text_length": [ function (value, params) { - return value.length == 0 || value.length >= +params; + return _.isUndefined(value) || value.length === 0 || value.length >= +params; }, $.mage.__('Please enter more or equal than {0} symbols.') ], "max_text_length": [ function (value, params) { - return value.length <= +params; + return !_.isUndefined(value) && value.length <= +params; }, $.mage.__('Please enter less or equal than {0} symbols.') ], diff --git a/app/code/Magento/Ui/view/base/web/js/lib/validation/utils.js b/app/code/Magento/Ui/view/base/web/js/lib/validation/utils.js index 99b1944a012f5..4ed81c10e0348 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/validation/utils.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/validation/utils.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define(function () { @@ -69,4 +69,4 @@ define(function () { } return utils; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js b/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js index 764b11dfbfea2..936da2e54fc36 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js @@ -1,5 +1,5 @@ /* - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js index b5313f7611e41..5d52acf0e4d38 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/bindings.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/bindings.js index 336a7f3b3c446..3c6db4827a5ad 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/bindings.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/bindings.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js index 9329422d2f26b..b2fb171b5e178 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js index d91b916df99bc..8b3a39b8ab847 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/modal/alert.js b/app/code/Magento/Ui/view/base/web/js/modal/alert.js index 73fbc62936aa4..241410bfa3abc 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/alert.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/alert.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/modal/confirm.js b/app/code/Magento/Ui/view/base/web/js/modal/confirm.js index 184db1f8c4a22..2bde2afd6faff 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/confirm.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/confirm.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/modal/modal-component.js b/app/code/Magento/Ui/view/base/web/js/modal/modal-component.js index 949db7f83707e..2dd75ae554d4a 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/modal-component.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/modal-component.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/modal/modal.js b/app/code/Magento/Ui/view/base/web/js/modal/modal.js index 759ea3be5e624..3c24f3db7ce9d 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/modal.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/modal.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/modal/modalToggle.js b/app/code/Magento/Ui/view/base/web/js/modal/modalToggle.js index fa4347d0df50e..8a717557536e3 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/modalToggle.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/modalToggle.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define([ diff --git a/app/code/Magento/Ui/view/base/web/js/modal/prompt.js b/app/code/Magento/Ui/view/base/web/js/modal/prompt.js index 67d3e01375818..9c4fcd6219694 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/prompt.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/prompt.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js b/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js index 1b59680881144..478ce528ae9cc 100644 --- a/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js +++ b/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js index 27678c477edf9..571b03317ac09 100644 --- a/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js +++ b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js @@ -1,5 +1,5 @@ /** - * Copyright © 2016 Magento. All rights reserved. + * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ 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 4639a32ff6fc9..9d32e2a795104 100644 --- a/app/code/Magento/Ui/view/base/web/templates/area.html +++ b/app/code/Magento/Ui/view/base/web/templates/area.html @@ -1,9 +1,9 @@
    - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/block-loader.html b/app/code/Magento/Ui/view/base/web/templates/block-loader.html index e7915bb9a4088..0f879e469371e 100644 --- a/app/code/Magento/Ui/view/base/web/templates/block-loader.html +++ b/app/code/Magento/Ui/view/base/web/templates/block-loader.html @@ -1,6 +1,6 @@ @@ -8,4 +8,4 @@
    Loading...
    -
    \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/collection.html b/app/code/Magento/Ui/view/base/web/templates/collection.html index 3ac74b0716660..1c515e5d311b7 100644 --- a/app/code/Magento/Ui/view/base/web/templates/collection.html +++ b/app/code/Magento/Ui/view/base/web/templates/collection.html @@ -1,6 +1,6 @@ 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 0dac3f792e0e2..3fee830c6bf40 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 @@ -1,6 +1,6 @@ @@ -16,4 +16,4 @@
    - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/action-delete.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/action-delete.html index a8a77d593fe98..209f6354f52de 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/action-delete.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/action-delete.html @@ -1,6 +1,6 @@ @@ -13,4 +13,4 @@ } "> - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/dnd.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/dnd.html index 95d3464bf3859..3068964174784 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/dnd.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/dnd.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/text.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/text.html index 0f48a294e6c0d..a8bc63109a688 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/text.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/text.html @@ -1,6 +1,6 @@ @@ -10,4 +10,4 @@ css: {_disabled: disabled} "> - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/thumbnail.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/thumbnail.html index e205b9933930a..5b74e4230fe42 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/thumbnail.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/cells/thumbnail.html @@ -1,7 +1,7 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html index 84a4114254830..6882d43b5c700 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/collapsible.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/default.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/default.html index b69c6b0de652a..6bb7da7cbaaf4 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/default.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/default.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html index 13f1bed36d297..712d9d0de2fad 100644 --- a/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html +++ b/app/code/Magento/Ui/view/base/web/templates/dynamic-rows/templates/grid.html @@ -1,6 +1,6 @@ @@ -78,4 +78,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/form/collection.html b/app/code/Magento/Ui/view/base/web/templates/form/collection.html index 8f98af63a8eba..72a0189ddb26e 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/collection.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/collection.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/button/container.html b/app/code/Magento/Ui/view/base/web/templates/form/components/button/container.html index 96b153e1208e0..4043db33abd09 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/button/container.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/button/container.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/button/simple.html b/app/code/Magento/Ui/view/base/web/templates/form/components/button/simple.html index 481010ca85f82..4d9f86697f449 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/button/simple.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/button/simple.html @@ -1,7 +1,7 @@ - \ No newline at end of file + 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 094baf9258053..75b5832027767 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 @@ -1,6 +1,6 @@ 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 e4d81c53f8a80..9ace6f80c569a 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 @@ -1,6 +1,6 @@ @@ -39,4 +39,4 @@
    - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/complex.html b/app/code/Magento/Ui/view/base/web/templates/form/components/complex.html index 39f3cfe322315..13bfc88d98238 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/complex.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/complex.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/single/checkbox.html b/app/code/Magento/Ui/view/base/web/templates/form/components/single/checkbox.html index b885ae9d8078f..9085e9f6368bd 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/single/checkbox.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/single/checkbox.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/single/field.html b/app/code/Magento/Ui/view/base/web/templates/form/components/single/field.html index 9c86e55dc0984..eb00b278acfaf 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/single/field.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/single/field.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html b/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html index 20722feea738a..95f604ad0397b 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/single/switcher.html b/app/code/Magento/Ui/view/base/web/templates/form/components/single/switcher.html index 4b467f8d7d4d3..aac8bc8dbf9aa 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/single/switcher.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/single/switcher.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/button.html b/app/code/Magento/Ui/view/base/web/templates/form/element/button.html index a0835388b50ba..432816f37a2ee 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/button.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/button.html @@ -1,6 +1,6 @@ @@ -14,4 +14,4 @@ attr="'data-index': index"> - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox-set.html b/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox-set.html index 48328690d701e..2a44c516850ad 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox-set.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/checkbox-set.html @@ -1,6 +1,6 @@ @@ -40,4 +40,4 @@ - \ No newline at end of file + 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 c4a4e43d1bee7..31bbaa2a82891 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 @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/date.html b/app/code/Magento/Ui/view/base/web/templates/form/element/date.html index 542b81fb918f1..e278455e12d2a 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/date.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/date.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/email.html b/app/code/Magento/Ui/view/base/web/templates/form/element/email.html index d90895c8ec242..00306b78ad620 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/email.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/email.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/helper/fallback-reset.html b/app/code/Magento/Ui/view/base/web/templates/form/element/helper/fallback-reset.html index e2cf3f80fc6d6..4bad21fc81a1a 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/helper/fallback-reset.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/helper/fallback-reset.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/helper/service.html b/app/code/Magento/Ui/view/base/web/templates/form/element/helper/service.html index 2fdb900fa1fbc..911c1e20b0065 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/helper/service.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/helper/service.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/helper/tooltip.html b/app/code/Magento/Ui/view/base/web/templates/form/element/helper/tooltip.html index 8ec294cc2cce4..b5d68b9b5e34b 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/helper/tooltip.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/helper/tooltip.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/hidden.html b/app/code/Magento/Ui/view/base/web/templates/form/element/hidden.html index c2973db15ee6c..dd0d5fbd10150 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/hidden.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/hidden.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/input.html b/app/code/Magento/Ui/view/base/web/templates/form/element/input.html index ad15f9436413d..b923b7e7b4475 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/input.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/input.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/media.html b/app/code/Magento/Ui/view/base/web/templates/form/element/media.html index 2b2bd0ad02bf9..b42e955fed5ec 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/media.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/media.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/multiselect.html b/app/code/Magento/Ui/view/base/web/templates/form/element/multiselect.html index 1745579b53078..6661dcfa42cb7 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/multiselect.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/multiselect.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/preview.html b/app/code/Magento/Ui/view/base/web/templates/form/element/preview.html index 06a8acbf13af9..c1f3609d7295e 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/preview.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/preview.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/price.html b/app/code/Magento/Ui/view/base/web/templates/form/element/price.html index 9ed4f36ecde0c..ae2155912cc25 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/price.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/price.html @@ -1,10 +1,10 @@
    -
    \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/radio.html b/app/code/Magento/Ui/view/base/web/templates/form/element/radio.html index 25b4785e03232..d7aea465eade2 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/radio.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/radio.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/select.html b/app/code/Magento/Ui/view/base/web/templates/form/element/select.html index 17bd01e3b1918..f7515b92c46e2 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/select.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/select.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/split-button.html b/app/code/Magento/Ui/view/base/web/templates/form/element/split-button.html index 5ca274540102f..ea8873fa395ce 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/split-button.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/split-button.html @@ -1,6 +1,6 @@ @@ -16,4 +16,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/switcher.html b/app/code/Magento/Ui/view/base/web/templates/form/element/switcher.html index 7529d07818294..f09865d0e53c2 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/switcher.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/switcher.html @@ -1,6 +1,6 @@ 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 597fcd75aa075..e07e4056af2dd 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 @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html index 91c2eb1bcd0dc..d9285957257b1 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html index 7415b4e6c330e..95ac7134f209a 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html @@ -1,6 +1,6 @@ @@ -30,4 +30,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/wysiwyg.html b/app/code/Magento/Ui/view/base/web/templates/form/element/wysiwyg.html index 6cd0efd96462c..04408cb845d43 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/wysiwyg.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/wysiwyg.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/form/field.html b/app/code/Magento/Ui/view/base/web/templates/form/field.html index 60f902a42d996..1d3b1cfc8895c 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/field.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/field.html @@ -1,6 +1,6 @@ @@ -40,4 +40,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/form/fieldset.html b/app/code/Magento/Ui/view/base/web/templates/form/fieldset.html index aeb93f48ff683..a97eb85b225dc 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/fieldset.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/fieldset.html @@ -1,6 +1,6 @@ @@ -9,7 +9,8 @@ attr="'data-level': $data.level, 'data-index': index" data-bind="visible: $data.visible === undefined ? true: $data.visible">
    @@ -19,8 +20,8 @@ '_changed': changed, '_loading': loading, '_error': error"> - - + + + data-bind="i18n: 'This tab contains invalid data. Please resolve this before saving.'"> @@ -43,7 +44,10 @@
    -
    + css="'admin__collapsible-content': collapsible, '_show': opened, '_hide': !opened()"> +
    diff --git a/app/code/Magento/Ui/view/base/web/templates/form/insert.html b/app/code/Magento/Ui/view/base/web/templates/form/insert.html index 118c910c66096..bf97bf8fbf01a 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/insert.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/insert.html @@ -1,6 +1,6 @@ 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 index f944d7ec38972..e9944a63bbbfe 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/actions.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html @@ -1,6 +1,6 @@ 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 index 00b9e090769f4..c7b0c49af3dcd 100644 --- 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 @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/html.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/html.html index 694517f48ebce..032b67d3b2fca 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/cells/html.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/html.html @@ -1,7 +1,7 @@ -
    \ No newline at end of file +
    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 index 1eb2129f67a11..7cc068fe723ec 100644 --- 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 @@ -1,6 +1,6 @@ @@ -14,4 +14,4 @@ id: index + 'check' + $row()[$col.indexField] }"> \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/onoff.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/onoff.html index fd37a20ec6b73..f927f578f0d1e 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/cells/onoff.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/onoff.html @@ -1,6 +1,6 @@ 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 index 6669461711087..725e6409feb8b 100644 --- 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 @@ -1,7 +1,7 @@ -
    \ No newline at end of file +
    diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail.html index 8e835357b1f2b..16447ab9f64d3 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail.html @@ -1,7 +1,7 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail/preview.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail/preview.html index 9020960d2262a..bc62199abeab9 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail/preview.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/thumbnail/preview.html @@ -1,6 +1,6 @@ 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 index 1e090d50b816d..5e10572651352 100644 --- 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 @@ -1,6 +1,6 @@ @@ -28,4 +28,4 @@
    - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/columns/onoff.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/onoff.html index 137b46d63a163..a5db2f959ca85 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/columns/onoff.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/onoff.html @@ -1,6 +1,6 @@ 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 index ce90150515371..1b29c95f1e5c1 100644 --- 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 @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html index e2b60900c246b..e338f76686b7b 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html index 5d3e64c94775e..a424d8040735b 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html @@ -1,6 +1,6 @@ @@ -37,4 +37,4 @@
    -
    \ No newline at end of file +
    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 index c14044de44eb2..627848b0d58f3 100644 --- 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 @@ -1,6 +1,6 @@ @@ -28,4 +28,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html b/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html index b2588ba9f362d..32c078d5eaa82 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/editing/field.html b/app/code/Magento/Ui/view/base/web/templates/grid/editing/field.html index 062e8e67e6c44..3cd1953d53539 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/editing/field.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/editing/field.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/editing/header-buttons.html b/app/code/Magento/Ui/view/base/web/templates/grid/editing/header-buttons.html index ab0131ed667cf..b79e45eaf6f81 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/editing/header-buttons.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/editing/header-buttons.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/editing/row-buttons.html b/app/code/Magento/Ui/view/base/web/templates/grid/editing/row-buttons.html index 7d6d804b1b537..6545e85222e68 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/editing/row-buttons.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/editing/row-buttons.html @@ -1,6 +1,6 @@ @@ -13,4 +13,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/editing/row.html b/app/code/Magento/Ui/view/base/web/templates/grid/editing/row.html index d8334806b463c..10ec4665c992e 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/editing/row.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/editing/row.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html b/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html index 7e632d94fdd34..f8ff827add0b8 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html @@ -1,6 +1,6 @@ @@ -25,4 +25,4 @@ @@ -177,7 +173,7 @@ data-action="close-advanced-select" type="button" data-bind="click: outerClick"> - + diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/field.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/field.html index 1d5290bc6cc2c..cfd818772bae9 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/filters/field.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/field.html @@ -1,6 +1,6 @@ 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 index 91a057a1b4226..7922d115e0223 100644 --- 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 @@ -1,6 +1,6 @@ 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 index 23de614a9fde5..3f1c9a47b9702 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/listing.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/listing.html @@ -1,6 +1,6 @@ @@ -19,4 +19,4 @@
    escapeHtml(__('Is Default')) ?>escapeHtml(__('Swatch')) ?> getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> + class="_required" + > + escapeHtml($_store->getName()) ?>
    +
    + getReadOnly() && !$block->canManageOptionDefaultOnly()):?> -
    getReadOnly() && !$block->canManageOptionDefaultOnly()): ?> -
    +
    +
    - getReadOnly() || $block->canManageOptionDefaultOnly()): ?> disabled="disabled"/> + getReadOnly() || $block->canManageOptionDefaultOnly()): ?> + disabled="disabled" + />
    - getReadOnly()):?>disabled="disabled"/> + getReadOnly()):?>disabled="disabled"/> - +
    -

    +

    escapeHtml(__('Choose a color')); ?>

    -
    -

    +
    +

    escapeHtml(__('Upload a file')); ?>

    -

    +

    escapeHtml(__('Clear')); ?>

    - getReadOnly() || $block->canManageOptionDefaultOnly()):?> disabled="disabled"/> + getReadOnly() || $block->canManageOptionDefaultOnly()):?> + disabled="disabled" + /> getReadOnly() && !$block->canManageOptionDefaultOnly()):?> -
    -
    \ No newline at end of file +
    diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging-total.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging-total.html index 0f0be27533de5..7bf15bd06004f 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/paging-total.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging-total.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging-detailed-total.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging-detailed-total.html index a6cdc696482c2..28c71dbe9d876 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging-detailed-total.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging-detailed-total.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html index 5563b9c867801..21cdc81c4742d 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html index 10d4708202adb..42f48f558658f 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html @@ -1,6 +1,6 @@ @@ -58,4 +58,4 @@ -